# -*- coding: utf-8 -*-

# Copyright 2009 David Lee Miller
#
# This file is part of POSSM (Python Open Source Scanning Microscopy).
#
# POSSM is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# POSSM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License         
# along with POSSM.  If not, see <http://www.gnu.org/licenses/>.
#                                                                           
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

from client import matplotlib,rcParams,cm,Toolbar,FigureCanvasWxAgg,NavigationToolbar2WxAgg
from client import Figure,nx,RectangleSelector,_load_bitmap
from client import copy,deepcopy,wx,time,ws,sv,os
from client import n #the numpy package
from pylabiv import SpecFigure
import sg_filter as sg
from shared.createtree import UnitOrganizer
import string,cmaps,wx.grid
TIMER_ID = wx.NewId()

class FakePkg(object):
	'A container to send old data in.'
	TYPE = 'fake'
	DATATYPE = 'None'
	UO = UnitOrganizer()
	def __init__(self,close=False):
		self.TYPE = None
		self.EXTENT = [0,10,0,10]
		self.SHAPE = (100,100)
		self.LINE = None
		self.data = None
		self.close = close
		self.ZSCALE = 1
		self.ZOUT = 1.0
		self.ZHV = 10.0

#class Plot3D(wx.Frame):
	#ASPECT_W = ws.ASPECT_W
	#ASPECT_H = ws.ASPECT_H
	#ASPECT_SIZE = ws.ASPECT_SIZE
	#TITLE_SIZE = ws.TITLE_SIZE
	#AXES_SIZE = ws.AXES_SIZE
	#DEFAULT_COLOR = ws.DEFAULT_COLOR
	#POINT_TYPE = ws.POINT_TYPE
	#LINE_WEIGHT = ws.LINE_WEIGHT
	#def __init__(self,parent,data):
		#name = 'N/A'
		#wx.Frame.__init__(self, parent, -1, name, style=wx.DEFAULT_FRAME_STYLE)
		#self.fig = Figure((self.ASPECT_W,self.ASPECT_H), self.ASPECT_SIZE)
		#self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
		#self.t = wx.Timer(self, TIMER_ID)
		#self.t.Start(10000)
		#self.txt = None
		#self.parent = parent
		#self.external = False
		#self.x = None
		#self.y = None
		#self.active = True
		#sizer = wx.FlexGridSizer(1,2,0,0)
		#panel_c = wx.Panel(self, -1)
		#sizer2 = wx.FlexGridSizer(2,1,0,0)

		#sizer2.Add(panel_c, 1, wx.EXPAND)
		#sizer.AddGrowableRow(0,1)
		#sizer.AddGrowableCol(0,1)
		#sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
		#sizer.Add(sizer2, 1, wx.LEFT|wx.TOP|wx.GROW)
		#self.SetSizer(sizer)
		#if not hasattr(self, 'subplot'):
                	#self.subplot = self.fig.add_subplot(111)
		#ax = p3.Axes3D(self.subplot)
		#self.statusBar = wx.StatusBar(self, -1)
		#self.statusBar.SetFieldsCount(1)
		#self.SetStatusBar(self.statusBar)
		
		#self.Fit()
		#self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		#self.Bind(wx.EVT_CLOSE, self.onClose)

		#self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
		#self.fig.clear()

		#self.Show()


class ScanProperties(wx.Frame):
	'''
	A flexible wx grid panel used to display an arbitrary number of scan attributes.
	'''
	def __init__(self,parent,package,name):
		self.package=package
		pkgdisplay={}
		for i in package.__dict__.keys():
			if type(package.__dict__[i])==tuple or type(package.__dict__[i])==list: pkgdisplay[i] = package.__dict__[i]
		namestr='Scan Properties '+name
		wx.Frame.__init__(self, parent, -1, namestr, style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER|wx.RESIZE_BOX|wx.MAXIMIZE_BOX))
		sizer = wx.FlexGridSizer(1,2,0,0)
		self.param_grid = wx.grid.Grid(self, -1, size=(1, 1))
		self.param_grid.CreateGrid(len(pkgdisplay.keys()), 3)
		self.param_grid.SetRowLabelSize(40)
		self.param_grid.SetColSize(0,100)
		self.param_grid.SetColSize(1,80)
		self.param_grid.SetColSize(2,80)
		self.param_grid.SetColLabelSize(30)
		self.param_grid.EnableDragColSize(1)
		self.param_grid.EnableDragRowSize(0)
		self.param_grid.EnableDragGridSize(0)
		self.param_grid.SetGridLineColour(wx.Colour(0, 0, 0))
		self.param_grid.SetLabelBackgroundColour(wx.Colour(238, 238, 238))
		self.param_grid.SetColLabelValue(0, "Name")
		self.param_grid.SetColLabelValue(1, "Value")
		self.param_grid.SetColLabelValue(2, "Unit")
		self.param_grid.SetMinSize((320, 300))
		attr = wx.grid.GridCellAttr()
		attr.SetReadOnly(True)
		self.param_grid.SetColAttr(0, attr)
		self.param_grid.SetColAttr(2, attr)
		self.param_grid.SetColAttr(1, attr)
		for i,j in enumerate(pkgdisplay.keys()):
			self.param_grid.SetCellValue(i,0,str(j))
			if len(pkgdisplay[j])==2:
				for k in range(1,3): self.param_grid.SetCellValue(i,k,str(pkgdisplay[j][k-1]))
			elif len(pkgdisplay[j])==1: self.param_grid.SetCellValue(i,0,str(pkgdisplay[j][0]))
		sizer.Add(self.param_grid)
		self.SetSizer(sizer)
		self.Fit()
		self.Show()

class LineProfile(wx.Frame):
	'''
	Creates a new window to display line-profile data from the notebook page.
	'''
	ASPECT_W = ws.ASPECT_W
	ASPECT_H = ws.ASPECT_H
	ASPECT_SIZE = ws.ASPECT_SIZE
	TITLE_SIZE = ws.TITLE_SIZE
	AXES_SIZE = ws.AXES_SIZE
	DEFAULT_COLOR = ws.DEFAULT_COLOR
	POINT_TYPE = ws.POINT_TYPE
	LINE_WEIGHT = ws.LINE_WEIGHT
	def __init__(self,parent,name,data,zunit,xscale,xunit,xory='X'):
		wx.Frame.__init__(self, parent, -1, name, style=wx.DEFAULT_FRAME_STYLE)
		self.fig = Figure((self.ASPECT_W,self.ASPECT_H), self.ASPECT_SIZE)
		self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
		self.t = wx.Timer(self, TIMER_ID)
		self.t.Start(10000)
		self.txt = None
		self.parent = parent
		if hasattr(parent,'selprof'): parent.selprof.Disable()
		self.external = False
		self.x = None
		self.y = None
		self.active = True
		self.zunit = zunit
		sizer = wx.FlexGridSizer(1,2,0,0)
		panel_c = wx.Panel(self, -1)
		sizer2 = wx.FlexGridSizer(2,1,0,0)
		
		self.xory=xory
		pro = wx.StaticBox(self, -1, 'Add Profile')
		setpro_label = wx.StaticText(self, -1, 'Set %s Location'%xory)
		if xory == 'X':
			self.setpro = wx.SpinCtrl(self, -1, '0', min=0, max=len(self.parent.display[:,0])-1)
		elif xory == 'Y':
			self.setpro = wx.SpinCtrl(self, -1, '0', min=0, max=len(self.parent.display[0,:])-1)
		else: pass
			
		sizer2a = wx.StaticBoxSizer(pro,wx.VERTICAL)
		if not xory == 'A':
			addpro = wx.Button(self, -1, 'Add to Plot')
			clearpro = wx.Button(self, -1, 'Clear All Profiles')
			setpro_label.SetMinSize((63,37))
			self.setpro.SetMinSize((63,27))
			addpro.SetMinSize((127,27))
			clearpro.SetMinSize((127,27))
			setpro_sizer = wx.BoxSizer(wx.HORIZONTAL)
			setpro_sizer.Add(setpro_label, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			setpro_sizer.Add(self.setpro, 0, wx.ADJUST_MINSIZE|wx.ALL, 8)
		
			sizer2a.Add(setpro_sizer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			sizer2a.Add(addpro, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			sizer2a.Add(clearpro, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
			sizer2.Add(sizer2a, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
			addpro.Bind(wx.EVT_BUTTON, self.AddProfile)
			clearpro.Bind(wx.EVT_BUTTON, self.ClearAll)
		
		savgol = wx.StaticBox(self, -1, 'Savitzky-Golay')
		savsizer = wx.BoxSizer(wx.HORIZONTAL)
		sgptssizer = wx.BoxSizer(wx.HORIZONTAL)
		sgpts_label = wx.StaticText(self,-1,'# Points:')
		self.sgpts = wx.SpinCtrl(self, -1, str(5), min=1, max=30)
		sgpts_label.SetMinSize((63,27))
		self.sgpts.SetMinSize((63,27))
		sgptssizer.Add(sgpts_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		sgptssizer.Add(self.sgpts, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pordersizer = wx.BoxSizer(wx.HORIZONTAL)
		porder_label = wx.StaticText(self,-1,'PolyOrder:')
		self.porder = wx.SpinCtrl(self, -1, str(1), min=1, max=5)
		porder_label.SetMinSize((63,27))
		self.porder.SetMinSize((63,27))
		pordersizer.Add(porder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pordersizer.Add(self.porder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		dordersizer = wx.BoxSizer(wx.HORIZONTAL)
		dorder_label = wx.StaticText(self,-1,'DerivOrder:')
		self.dorder = wx.SpinCtrl(self, -1, str(1), min=0, max=5)
		dorder_label.SetMinSize((63,27))
		self.dorder.SetMinSize((63,27))
		dordersizer.Add(dorder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		dordersizer.Add(self.dorder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		self.sgupdate = wx.Button(self, -1, 'Apply')
		self.sgupdate.SetMinSize((127,27))
		sizer2f = wx.StaticBoxSizer(savgol,wx.VERTICAL)
		sizer2f.Add(sgptssizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(pordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(dordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgupdate, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		
		sizer2.Add(sizer2f, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_c, 1, wx.EXPAND)
		sizer.AddGrowableRow(0,1)
		sizer.AddGrowableCol(0,1)
		sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
		sizer.Add(sizer2, 1, wx.LEFT|wx.TOP|wx.GROW)
		self.SetSizer(sizer)
		self.data = data
		self.sgupdate.Bind(wx.EVT_BUTTON, self.OnSG)
		
		self.statusBar = wx.StatusBar(self, -1)
		self.statusBar.SetFieldsCount(1)
		self.SetStatusBar(self.statusBar)
		
		self.Fit()
		self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		self.Bind(wx.EVT_CLOSE, self.onClose)

		self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
		self.fig.clear()
		if not hasattr(self, 'subplot'):
                	self.subplot = self.fig.add_subplot(111)
		self.fig.subplots_adjust(left=0.15, bottom=0.2)
		xdata=n.array(range(len(data)))*xscale
		self.asdf = self.subplot.plot(xdata,data,lw=self.LINE_WEIGHT)
		self.subplot.set_ylabel("Z Value ("+self.zunit+")", fontsize = self.AXES_SIZE)
		if xory == 'X': xory_r = 'Y'
		else: xory_r = 'X'
		self.subplot.set_xlabel(xory_r+" Distance (%s)"%xunit, fontsize = self.AXES_SIZE)
		
		self.Show()
	
	def OnSG(self,event):
		gradpts = int(self.sgpts.GetValue())
		polyorder = int(self.porder.GetValue())
		sgderiv = int(self.dorder.GetValue())
		if sgderiv > polyorder:
			self.porder.SetValue(int(sgderiv))
			polyorder = sgderiv
		self.display = deepcopy(self.data)
		coeff = sg.calc_coeff(gradpts, polyorder, sgderiv)
		dx = 1
		corr = (1./dx)**sgderiv
		#if sgderiv != 0: corr *= -1
		#else: corr *= 1
		self.display = sg.savitzky_golay(self.display,kernel=2*gradpts+1,order=polyorder,deriv=sgderiv)
		self.subplot.clear()
		self.subplot.set_ylabel("Z Value ("+self.zunit+")", fontsize = self.AXES_SIZE)
		self.subplot.plot(self.display,lw=self.LINE_WEIGHT)
		self.canvas.draw()
	
	def onTimer(self, evt):
		self.canvas.draw()
	
	def onClose(self, evt):
		self.active = False
		self.t.Stop()
		if hasattr(self.parent,'selprof'): self.parent.selprof.Enable()
		if hasattr(self.parent,'proline') and self.xory=='A':
			self.parent.proline.remove()
			self.parent.canvas.draw()
		evt.Skip()
	
	def AddProfile(self, event):
		loc = int(self.setpro.GetValue())
		if self.xory == 'Y':
			self.subplot.plot(self.parent.display[loc,:],lw=self.LINE_WEIGHT)
		elif self.xory == 'X':
			self.subplot.plot(self.parent.display[:,loc],lw=self.LINE_WEIGHT)
		self.canvas.draw()
	
	def ClearAll(self, event):
		self.subplot.clear()
		self.canvas.draw()
	
	def UpdateStatusBar(self, event):
		if event.inaxes:
			self.x, self.y = event.xdata, event.ydata
			self.statusBar.SetStatusText(( "x= " + str(self.x)[:5] +
							"  y=" +str(self.y)[:5] ),0)

class MakeHist(wx.Frame):
	'''
	Creates a histogram for adjusting the z-limits of the image. Takes mouse input and
	uses the selected values to change the image contrast.
	'''
	ASPECT_W = ws.ASPECT_W
	ASPECT_H = ws.ASPECT_H
	ASPECT_SIZE = ws.ASPECT_SIZE
	TITLE_SIZE = ws.TITLE_SIZE
	AXES_SIZE = ws.AXES_SIZE
	DEFAULT_COLOR = ws.DEFAULT_COLOR
	POINT_TYPE = ws.POINT_TYPE
	left = None
	right = None
	def __init__(self,parent,name,data2):
		wx.Frame.__init__(self, parent, -1, name, style=wx.DEFAULT_FRAME_STYLE)
		self.fig = Figure((self.ASPECT_W,self.ASPECT_H), self.ASPECT_SIZE)
		self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
		self.t = wx.Timer(self, TIMER_ID)
		self.t.Start(10000)
		self.txt = None
		self.parent = parent
		self.external = False
		self.x = None
		self.y = None
		self.active = True

		data=n.array([])
		for i in range(data2.shape[0]):
			if n.ptp(data2[i]) > 0: data=n.append(data,data2[i])
		sizer = wx.FlexGridSizer(1,2,0,0)
		panel_c = wx.Panel(self, -1)
		sizer2 = wx.FlexGridSizer(2,1,0,0)
		
		hist = wx.StaticBox(self, -1, 'Level Adjustments')
		setlevels = wx.Button(self, -1, 'Set Custom Levels')
		setauto = wx.Button(self, -1, 'Set Auto Levels')
		setlevels.SetMinSize((127,27))
		setauto.SetMinSize((127,27))
		sizer2a = wx.StaticBoxSizer(hist,wx.VERTICAL)
		sizer2a.Add(setlevels, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a.Add(setauto, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		area = wx.StaticBox(self, -1, 'Plot Area')
		exleft = wx.Button(self, -1, '<-- L')
		conleft = wx.Button(self, -1, '--> L')
		conright = wx.Button(self, -1, '<-- R')
		exright = wx.Button(self, -1, '--> R')
		exleft.SetMinSize((63,27))
		conleft.SetMinSize((63,27))
		exright.SetMinSize((63,27))
		conright.SetMinSize((63,27))
		sizerl = wx.BoxSizer(wx.HORIZONTAL)
		sizerr = wx.BoxSizer(wx.HORIZONTAL)
		sizer2b = wx.StaticBoxSizer(area,wx.VERTICAL)
		sizerl.Add(exleft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizerl.Add(conleft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizerr.Add(conright, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizerr.Add(exright, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2b.Add(sizerl)
		sizer2b.Add(sizerr)
		
		self.histadj = wx.CheckBox(self, -1, label='Expand Y')
		self.histadj.SetMinSize((127,27))
		uphist = wx.StaticBox(self, -1, 'Update Histogram')
		update = wx.Button(self, -1, 'Update')
		update.SetMinSize((127,27))
		sizer2c = wx.StaticBoxSizer(uphist,wx.VERTICAL)
		sizer2c.Add(self.histadj, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2c.Add(update, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		sizer2.Add(sizer2a, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2b, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2c, 1, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_c, 1, wx.EXPAND)
		
		sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
		sizer.Add(sizer2, 1, wx.LEFT|wx.TOP|wx.GROW)
		self.SetSizer(sizer)


		self.statusBar = wx.StatusBar(self, -1)
		self.statusBar.SetFieldsCount(1)
		self.SetStatusBar(self.statusBar)
		
		self.Fit()
		self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		setlevels.Bind(wx.EVT_BUTTON, self.SetLevels)
		setauto.Bind(wx.EVT_BUTTON, self.SetAuto)
		exright.Bind(wx.EVT_BUTTON, self.ExRight)
		conright.Bind(wx.EVT_BUTTON, self.ConRight)
		exleft.Bind(wx.EVT_BUTTON, self.ExLeft)
		conleft.Bind(wx.EVT_BUTTON, self.ConLeft)
		update.Bind(wx.EVT_BUTTON, self.OnUp)
		self.histadj.Bind(wx.EVT_CHECKBOX, self.OnScale)
		self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnAdjustL)
		self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnAdjustR)
		self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.OnMWheel)
		self.canvas.mpl_connect('motion_notify_event', self.UpdateStatusBar)
		self.fig.clear()
		if not hasattr(self, 'subplot'):
                	self.subplot = self.fig.add_subplot(111)
		self.fig.subplots_adjust(left=0.15, bottom=0.2)
		self.asdf = self.subplot.hist(data.flatten(), 75, normed=1, facecolor='green', alpha=0.75)
		self.subplot.set_xlabel("Z Value", fontsize = self.AXES_SIZE)
		
		self.leftval,self.rightval = self.parent.im.get_clim()
		self.right = self.subplot.axvline(x=self.rightval, color='r', alpha=0.9)
		self.left = self.subplot.axvline(x=self.leftval, color='g', alpha=0.9)
		self.zmax = n.max(data)
		self.zmin = n.min(data)
		self.zwidth = self.zmax-self.zmin
		self.rmult = 0
		self.lmult = 0
		self.Show()
	
	def OnScale(self, event):
		if self.histadj.GetValue():
			ymax = n.mean(self.asdf[0])+n.std(self.asdf[0])
			self.subplot.set_ylim((0,ymax))
		else:
			self.subplot.set_ylim((0,n.array(self.asdf[0]).max()))
		self.canvas.draw()
	
	def OnAdjustL(self, event, draw=True):
		#if self.left: self.left.remove()
		self.leftval = copy(self.x)
		if self.leftval > self.rightval: self.leftval = copy(self.rightval)
		self.left.set_xdata(self.leftval)
		self.subplot.draw_artist(self.left)
		#self.left = self.subplot.axvline(x=self.leftval, color='g', alpha=0.9) #draws the vertical line
		if draw: self.canvas.draw()
	
	def OnMWheel(self, event):
		wheel = event.GetWheelRotation()
		if wheel > 0:
			self.x = self.leftval + self.zwidth/200.
			self.OnAdjustL(None, draw=False)
			self.x = self.rightval + self.zwidth/200.
			self.OnAdjustR(None)
		elif wheel < 0:
			self.x = self.leftval - self.zwidth/200.
			self.OnAdjustL(None, draw=False)
			self.x = self.rightval - self.zwidth/200.
			self.OnAdjustR(None)
	
	def OnAdjustR(self, event, draw=True):
		#if self.right: self.right.remove()
		self.rightval = copy(self.x)
		if self.rightval < self.leftval: self.rightval = copy(self.leftval)
		self.right.set_xdata(self.rightval)
		self.subplot.draw_artist(self.right)
		#self.right = self.subplot.axvline(x=self.rightval, color='r', alpha=0.9) #draws the vertical line
		if draw: self.canvas.draw()
	
	def onClose(self, evt):
		self.active = False
		self.t.Stop()
		evt.Skip()
		
	def onTimer(self, evt):
		self.canvas.draw()
		
	def UpdateStatusBar(self, event):
		if event.inaxes:
			self.x, self.y = event.xdata, event.ydata
			self.statusBar.SetStatusText(( "x= " + str(self.x)[:5] +
							"  y=" +str(self.y)[:5] ),
							0)
	
	def SetLevels(self, event):
		self.parent.SetLim(zmin=self.leftval,zmax=self.rightval)
	
	def SetAuto(self, event):
		zmax = n.mean(self.parent.display)+2*n.std(self.parent.display)
		zmin = n.mean(self.parent.display)-2*n.std(self.parent.display)
		self.parent.SetLim(zmin=zmin,zmax=zmax)
		self.leftval,self.rightval = self.parent.im.get_clim()
		self.x = copy(self.leftval)
		self.OnAdjustL(None)
		self.x = copy(self.rightval)
		self.OnAdjustR(None)
		self.rmult = 0
		self.lmult = 0
		self.canvas.draw()
	
	def OnUp(self, event):
		self.subplot.clear()
		self.asdf = self.subplot.hist(self.parent.display.flatten(), 75, normed=1, facecolor='green', alpha=0.75)
		self.subplot.set_xlabel("Z Value", fontsize = self.AXES_SIZE)
		self.leftval,self.rightval = self.parent.im.get_clim()
		self.right = self.subplot.axvline(x=self.rightval, color='r', alpha=0.9)
		self.left = self.subplot.axvline(x=self.leftval, color='g', alpha=0.9)
		self.OnScale(event)
	
	def ExRight(self, event):
		self.rmult += 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmax + self.rmult*adj
		self.OnAdjustR(None)
		
	def ConRight(self, event):
		self.rmult -= 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmax + self.rmult*adj
		self.OnAdjustR(None)
		
	def ExLeft(self, event):
		self.lmult -= 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmin + self.lmult*adj
		self.OnAdjustL(None)
		
	def ConLeft(self, event):
		self.lmult += 1
		zmin = n.min(self.parent.display)
		zmax = n.max(self.parent.display)
		width = (zmax-zmin)
		adj = 0.05*width
		self.x = zmin + self.lmult*adj
		self.OnAdjustL(None)


class MyNavigationToolbar(NavigationToolbar2WxAgg):
	"""
	Extend the default wx toolbar with your own event handlers
	"""
	ON_IV = wx.NewId()
	ON_GRAY = wx.NewId()
	ON_SPEC = wx.NewId()
	ON_MASK = wx.NewId()
	ON_SPECDISP = wx.NewId()
	def __init__(self, parent, canvas, cankill, specselect=False):
		NavigationToolbar2WxAgg.__init__(self, canvas)
		self.a = None
		self.fig = None
		self.transiv = None
		self.ivsw = 0
		self.graysw = 0
		self.setcolor = cm.jet
		self.parent = parent
		# for simplicity I'm going to reuse a bitmap from wx, you'll
		# probably want to add your own.
		#if specselect:
			#self.AddSimpleTool(self.ON_SPEC, _load_bitmap('stock_close.xpm'),
						#'Select Spectroscopy Points', 'Toggle Spectroscopy Selector')
			#wx.EVT_TOOL(self, self.ON_SPEC, self.parent.toggle_selector)
	
	def _addMaskToggle(self):
		self.AddSimpleTool(self.ON_MASK, _load_bitmap('stock_close.xpm'),
					'Toggle Spectroscopy Mask', 'Toggle Spectroscopy Mask')
		wx.EVT_TOOL(self, self.ON_MASK, self.parent.toggle_mask)
	
	def _addSpecToggle(self):
		self.AddSimpleTool(self.ON_SPECDISP, _load_bitmap('stock_close.xpm'),
					'Open Spectroscopy Viewer', 'Open Spectroscopy Viewer')
		wx.EVT_TOOL(self, self.ON_SPECDISP, self.parent.toggle_spec)

class NotebookPage(wx.Panel):
	NB_TYPE = 'image'
	im = None
	transspec = None
	mask=None
	imagepath=ws.IMAGEPATH
	#cmap = {'gray':cm.gray,'pink':cm.pink,'hot':cm.hot,'jet':cm.jet,'summer':cm.summer,'spring':cm.spring,\
	#'winter':cm.winter,'autumn':cm.autumn,'flag':cm.flag,'hsv':cm.hsv,'prism':cm.prism,\
	#'stern':cm.gist_stern,'rainbow':cm.gist_rainbow,'earth':cm.gist_earth,'ncar':cm.gist_ncar,'cool':cm.cool,\
	#'copper':cm.copper,'bone':cm.bone}
	#cmap_r = {'gray':cm.gray_r,'pink':cm.pink_r,'hot':cm.hot_r,'jet':cm.jet_r,'summer':cm.summer_r,'spring':cm.spring_r,\
	#'winter':cm.winter_r,'autumn':cm.autumn_r,'flag':cm.flag_r,'hsv':cm.hsv_r,'prism':cm.prism_r,\
	#'stern':cm.gist_stern_r,'rainbow':cm.gist_rainbow_r,'earth':cm.gist_earth_r,'ncar':cm.gist_ncar_r,'cool':cm.cool_r,\
	#'copper':cm.copper_r,'bone':cm.bone_r}
	cmap = cmaps.cmap
	cmap_r = cmaps.cmap_r
	interps = ['--Interp--','bilinear','bicubic','nearest','spline16','spline36',\
	'hanning','hamming','hermite','kaiser','quadric','catrom','gaussian','bessel','mitchell',\
	'sinc','lanczos','blackman']
	currcmap = cmap[ws.DEFAULT_CMAP]
	currinterp = ws.DEFAULT_INTERP
	currfrad = 1
	bkim = None
	curralpha = 1.0
	lineN=0
	ax = 0
	ay = 0
	pave = 0
	coeff = []
	gradpts = 3
	polyorder = 1
	sgderiv = 1
	direc = 0
	mblayer = 0
	dist_unit = ['Volts','Angstroms','Nanometers','Microns']
	current_unit = ['Volts','NanoAmps','PicoAmps']
	xyunit = dist_unit[1]
	zunit = dist_unit[1]
	iunit = current_unit[0]
	scalebar=[None,None]
	fps = ws.MAX_FPS
	def __init__(self,frame,parent,pagenum,editor=None):
		wx.Panel.__init__(self,parent)
		self.parent = parent
		self.frame = frame
		self.pagenum = pagenum
		self.editor=editor
	
	def addPlot(self,figure,datapkg,addlabels=None,smiley=False,fake=False):
		self.figure = figure
		if smiley:
			self.data = datapkg.data
			self.display = datapkg.data
		else:
			if datapkg.SHAPE[0] == datapkg.SHAPE[1]:
				if hasattr(datapkg,'IMAGEDATA'):
					self.data = n.array(datapkg.IMAGEDATA[0][0])
					self.display = n.array(deepcopy(datapkg.IMAGEDATA[0][0]))
				elif fake:
					self.data = n.eye(datapkg.SHAPE[0])
					self.display = n.eye(datapkg.SHAPE[0])
					for i in range(len(self.display[:])):
						for j in range(len(self.display[0,:])):
							#self.data[i,j] = 2*n.sin(i/4.)+2*n.sin(j/4.)
							#self.display[i,j] = 2*n.sin(i/4.)+2*n.sin(j/4.)
							self.data[i,j] = 2*n.cos(0.125*(4*n.pi/2.46)*(1/n.sqrt(3.))*j)+2*n.cos(0.125*(2*n.pi/2.46)*((1/n.sqrt(3.))*j+i))+2*n.cos(0.125*(2*n.pi/2.46)*((-1/n.sqrt(3.))*j+i))
							self.display[i,j] = 2*n.cos(0.125*(4*n.pi/2.46)*(1/n.sqrt(3.))*j)+2*n.cos(0.125*(2*n.pi/2.46)*((1/n.sqrt(3.))*j+i))+2*n.cos(0.125*(2*n.pi/2.46)*((-1/n.sqrt(3.))*j+i))
				else:
					self.data = n.zeros(datapkg.SHAPE)
					self.display = n.zeros(datapkg.SHAPE)
			else:
				self.data = n.zeros(datapkg.SHAPE)
				self.display = n.zeros(datapkg.SHAPE)
				self.display[0,1] = 1
		if datapkg.TYPE in self.frame.imagespec:
			specselect=True
			self.extent = None
			self.spec_mask=datapkg.SPEC_MASK
			self.GRIDX = datapkg.GRIDX
			self.GRIDY = datapkg.GRIDY
			self.checker = datapkg.CHECKER
		else:
			specselect=False
			self.extent = datapkg.EXTENT
		if hasattr(datapkg,'ZSCALE'): self.ZSCALE = datapkg.ZSCALE
		else: self.ZSCALE = 1
		if hasattr(datapkg, 'ZOUT'): self.ZOUT = datapkg.ZOUT
		else: self.ZOUT = 1.0
		if hasattr(datapkg, 'ZHV'): self.ZHV = datapkg.ZHV
		else: self.ZHV = 10.0
		self.UO = datapkg.UO
		self.shape = datapkg.SHAPE
		self.canvas = FigureCanvasWxAgg(self, -1, figure)
		self.toolbar = MyNavigationToolbar(self,self.canvas, True, specselect=specselect)
		self.toolbar.Realize()
		self._set_layout(addlabels=addlabels)
		self.subplot = figure.add_subplot(111)
		self.scalebar=[None,None]
		if self.extent:
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.subplot.set_xlabel('X (Pixels)')
			self.subplot.set_ylabel('Y (Pixels)')
			#levels = n.arange(self.display.min(), self.display.max(), self.display.std())
			#CS = self.subplot.contour(self.display, levels,origin='lower',linewidths=2)
			#self.subplot.clabel(CS,inline=1,fmt='%1.1f',fontsize=12)
		else:
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.subplot.set_xlabel('X (Pixels)')
			self.subplot.set_ylabel('Y (Pixels)')
		#if specselect:
			#self.span = RectangleSelector(self.im.axes, self.onselect,drawtype='box',useblit=True,\
			#minspanx=0,minspany=0)
		self.colorbar = self.figure.colorbar(self.im,shrink=0.8)
		self.colorbar.draw_all()
		self.subplot.set_title('Scan No. '+self.SCAN)
		#self.figure.subplots_adjust(left=0.15, bottom=0.15)
		self.canvas.draw()
		self.starttime = time.time()
		self.timer = wx.Timer(self, id=102)
		self.timer.Start(1000)
		self.Bind(wx.EVT_TIMER, self.ElapsedTime, id=102)
		#self.im.set_data(self.data)
		#self.Update(None,0,noline=True)
	
	def _set_layout(self,addlabels=None):
		panel_b = wx.Panel(self, -1)
		#panel_c = wx.Panel(self, -1)
		#panel_c.SetMinSize((127, 27))
		sizer = wx.FlexGridSizer(2, 1, 0, 0)
		sizer.AddGrowableRow(1,1)
		sizer.AddGrowableCol(0,1)
		sizer.Add(self.toolbar, 1, wx.ADJUST_MINSIZE, 0)
		sizer.Add(self.canvas, 1, wx.GROW, 0)
		#sizer.Add(panel_c, 0, wx.GROW, 0)
		sizer2 = wx.BoxSizer(wx.VERTICAL)
		sizer3 = wx.BoxSizer(wx.VERTICAL)
		sizer4 = wx.BoxSizer(wx.HORIZONTAL)
		padj = wx.StaticBox(self, -1, 'Plot Adjustments')
		self.colors = wx.Choice(self, -1, choices=['-Colors-']+self.cmap.keys())
		self.colors.SetStringSelection(ws.DEFAULT_CMAP)
		self.colinv = wx.CheckBox(self, -1, 'Inv')
		self.interp = wx.Choice(self, -1, choices=self.interps)
		self.colors.SetMinSize((85,27))
		self.colinv.SetMinSize((42,27))
		self.interp.SetMinSize((127,27))
		#sizercol = wx.BoxSizer(wx.HORIZONTAL)
		sizercol = wx.FlexGridSizer(1, 2, 0, 0)
		sizercol.Add(self.colors, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizercol.Add(self.colinv, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a = wx.StaticBoxSizer(padj,wx.VERTICAL)
		#sizer2a.Add(self.colors, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a.Add(sizercol, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2a.Add(self.interp, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		iadj = wx.StaticBox(self, -1,'Interp Tuning')
		fradsizer = wx.BoxSizer(wx.HORIZONTAL)
		frad_label = wx.StaticText(self,-1,'Radius')
		self.frad = wx.SpinCtrl(self, -1, '1', min=1, max=5000)
		frad_label.SetMinSize((63,27))
		self.frad.SetMinSize((63,27))
		fradsizer.Add(frad_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		fradsizer.Add(self.frad, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pixsizer = wx.BoxSizer(wx.HORIZONTAL)
		pix_label = wx.StaticText(self,-1,'Pixels:')
		self.pix = wx.StaticText(self, -1, '0.1')
		self.setrad = wx.Button(self, -1, 'Set Radius')
		pix_label.SetMinSize((63,27))
		self.pix.SetMinSize((63,27))
		self.setrad.SetMinSize((127,27))
		pixsizer.Add(pix_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pixsizer.Add(self.pix, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		sizer2b = wx.StaticBoxSizer(iadj,wx.VERTICAL)
		sizer2b.Add(fradsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2b.Add(pixsizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2b.Add(self.setrad, 0, wx.ADJUST_MINSIZE, 0)
		
		#bkg = wx.StaticBox(self, -1,'Background')
		#backgrounds = ['--Background--','None']+copy(self.frame.pages.keys())
		#self.bkim_box = wx.Choice(self, -1, choices=backgrounds)
		#alphasizer = wx.BoxSizer(wx.HORIZONTAL)
		#alpha_label = wx.StaticText(self,-1,'Alpha%')
		#self.alpha = wx.SpinCtrl(self, -1, '1', min=1, max=100)
		#alpha_label.SetMinSize((63,27))
		#self.alpha.SetMinSize((63,27))
		#alphasizer.Add(alpha_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		#alphasizer.Add(self.alpha, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		#setalpha = wx.Button(self, -1, 'Set Alpha')
		#setalpha.SetMinSize((127,27))
		#self.bkim_box.SetMinSize((127,27))
		#sizer2c = wx.StaticBoxSizer(bkg,wx.VERTICAL)
		#sizer2c.Add(self.bkim_box, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer2c.Add(alphasizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		#sizer2c.Add(setalpha, 0, wx.ADJUST_MINSIZE, 0)
		#self.bkim_box.Disable()
		#setalpha.Disable()
		#self.alpha.Disable()
		
		prof = wx.StaticBox(self, -1,'Profiles')
		profiles = ['--Profiles--','Vertical','Horizontal','Arbitrary']
		self.prof_box = wx.Choice(self, -1, choices=profiles)
		#alphasizer = wx.BoxSizer(wx.HORIZONTAL)
		#alpha_label = wx.StaticText(self,-1,'Alpha%')
		#self.alpha = wx.SpinCtrl(self, -1, '1', min=1, max=100)
		#alpha_label.SetMinSize((63,27))
		#self.alpha.SetMinSize((63,27))
		#alphasizer.Add(alpha_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		#alphasizer.Add(self.alpha, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		selprof = wx.Button(self, -1, 'Select Profile')
		selprof.SetMinSize((127,27))
		self.selprof=selprof
		self.prof_box.SetMinSize((127,27))
		sizer2c = wx.StaticBoxSizer(prof,wx.VERTICAL)
		sizer2c.Add(self.prof_box, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer2c.Add(alphasizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2c.Add(selprof, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#self.prof_box.Disable()
		#setalpha.Disable()
		#self.alpha.Disable()
		
		prog = wx.StaticBox(self, -1, 'Progress')
		self.gauge = wx.Gauge(self, -1, self.shape[0]-1,name='Progress..')
		progsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.elapsedtime = wx.StaticText(self,-1,'Elapsed Time')
		self.displayprop = wx.Button(self, -1, 'Properties')
		self.expimage = wx.Button(self, -1, 'Export to LaTeX')
		self.elapsedtime.SetMinSize((127,27))
		self.gauge.SetMinSize((127,27))
		self.displayprop.SetMinSize((127,27))
		self.expimage.SetMinSize((127,27))
		sizer2d = wx.StaticBoxSizer(prog,wx.VERTICAL)
		sizer2d.Add(self.gauge, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT|wx.TOP, 5)
		sizer2d.Add(self.elapsedtime, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2d.Add(self.displayprop, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2d.Add(self.expimage, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		
		savgol = wx.StaticBox(self, -1, 'Savitzky-Golay')
		savsizer = wx.BoxSizer(wx.HORIZONTAL)
		sgptssizer = wx.BoxSizer(wx.HORIZONTAL)
		sgpts_label = wx.StaticText(self,-1,'# Points:')
		self.sgpts = wx.SpinCtrl(self, -1, str(self.gradpts), min=1, max=30)
		sgpts_label.SetMinSize((63,27))
		self.sgpts.SetMinSize((63,27))
		sgptssizer.Add(sgpts_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		sgptssizer.Add(self.sgpts, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pordersizer = wx.BoxSizer(wx.HORIZONTAL)
		porder_label = wx.StaticText(self,-1,'PolyOrder:')
		self.porder = wx.SpinCtrl(self, -1, str(self.polyorder), min=1, max=5)
		porder_label.SetMinSize((63,27))
		self.porder.SetMinSize((63,27))
		pordersizer.Add(porder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pordersizer.Add(self.porder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		dordersizer = wx.BoxSizer(wx.HORIZONTAL)
		dorder_label = wx.StaticText(self,-1,'DerivOrder:')
		self.dorder = wx.SpinCtrl(self, -1, str(self.sgderiv), min=0, max=5)
		dorder_label.SetMinSize((63,27))
		self.dorder.SetMinSize((63,27))
		dordersizer.Add(dorder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		dordersizer.Add(self.dorder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		self.sgupdate = wx.Button(self, -1, 'Apply')
		self.sgupdate.SetMinSize((127,27))
		self.sgclear = wx.Button(self, -1, 'Clear')
		self.sgclear.SetMinSize((127,27))
		sizer2f = wx.StaticBoxSizer(savgol,wx.VERTICAL)
		sizer2f.Add(sgptssizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(pordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(dordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgupdate, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgclear, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		fftbox = wx.StaticBox(self, -1, 'FFT/Filter')
		self.fftlog = wx.CheckBox(self, -1, label='Log Display')
		self.showfft = wx.ToggleButton(self, -1, 'Twin View')
		self.APPLY_ID = wx.NewId()
		self.applyfft = wx.Button(self, self.APPLY_ID, 'Apply')
		self.clearfft = wx.Button(self, -1, 'Clear')
		padtxt = wx.StaticText(self,-1,'Pad 0s')
		self.padval=wx.SpinCtrl(self,-1,'0',min=0,max=1000)
		self.windowfft=wx.Choice(self,-1,choices=('None','hanning','hamming','bartlett','blackman'))
		self.maskfft=wx.Choice(self,-1,choices=('Square','4-Fold','4-Fold Inverse','6-Fold','6-Fold Inverse'))
		self.selectmaskfft=wx.Button(self,-1,'Select')
		self.filterfft=wx.Button(self,-1,'Filter')
		self.clearfilterfft=wx.Button(self,-1,'Clear')
		filterpixtxt=wx.StaticText(self,-1,'Pixels')
		self.filterpix=wx.SpinCtrl(self,-1,'1',min=1,max=100)
		fftsizer = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer2 = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer3 = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer4 = wx.BoxSizer(wx.HORIZONTAL)
		fftsizer5 = wx.BoxSizer(wx.HORIZONTAL)
		self.fftlog.SetMinSize((127,27))
		self.showfft.SetMinSize((127,27))
		self.windowfft.SetMinSize((127,27))
		self.maskfft.SetMinSize((62,27))
		self.selectmaskfft.SetMinSize((62,27))
		self.applyfft.SetMinSize((62,27))
		self.clearfft.SetMinSize((62,27))
		self.filterfft.SetMinSize((62,27))
		self.clearfilterfft.SetMinSize((62,27))
		self.filterfft.Disable()
		self.filterpix.Disable()
		self.selectmaskfft.Disable()
		self.maskfft.Disable()
		fftsizer2.Add(self.applyfft, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 2)
		fftsizer2.Add(self.clearfft, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		fftsizer3.Add(self.filterfft, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 2)
		fftsizer3.Add(self.clearfilterfft, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		fftsizer5.Add(self.selectmaskfft, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 2)
		fftsizer5.Add(self.maskfft, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		padtxt.SetMinSize((57,27))
		self.padval.SetMinSize((62,27))
		fftsizer.Add(padtxt, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		fftsizer.Add(self.padval, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		filterpixtxt.SetMinSize((57,27))
		self.filterpix.SetMinSize((62,27))
		fftsizer4.Add(filterpixtxt, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		fftsizer4.Add(self.filterpix, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		sizer2g = wx.StaticBoxSizer(fftbox,wx.VERTICAL)
		sizer2g.Add(self.fftlog, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(self.showfft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(self.windowfft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer5, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer4, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(fftsizer3, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		subtr = wx.StaticBox(self, -1, 'Subtraction')
		self.subtr = wx.Choice(self, -1, choices=['--Subtraction--','None','Line','Plane'])
		self.showhist = wx.Button(self, -1, 'Show Histogram')
		progsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.subtr.SetMinSize((127,27))
		self.showhist.SetMinSize((127,27))
		sizer2e = wx.StaticBoxSizer(subtr,wx.VERTICAL)
		sizer2e.Add(self.subtr, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2e.Add(self.showhist, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2a, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2b, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2e, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2f, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer2.Add(sizer2g, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2c, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2d, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_b, 1, wx.EXPAND, 0)
		
		unitbox = wx.StaticBox(self, -1, 'Units')
		unit_types = ['XY','Z','I']
		self.unit_type = wx.Choice(self, -1, choices=unit_types)
		self.use_unit = wx.Choice(self, -1, choices=self.dist_unit)
		#self.unit_apply = wx.Button(self, -1, 'Apply')
		self.show_scale = wx.Choice(self, -1, choices=['0','25','50','75','100'])
		self.show_scale.Disable()
		showscaletext = wx.StaticText(self,-1,'Alpha')
		self.scale_colorR = wx.Choice(self, -1, choices=['R','0','2','4','6','8','a','c','e'])
		self.scale_colorG= wx.Choice(self, -1, choices=['G','0','2','4','6','8','a','c','e'])
		self.scale_colorB= wx.Choice(self, -1, choices=['B','0','2','4','6','8','a','c','e'])
		unitsizer1 = wx.BoxSizer(wx.HORIZONTAL)
		unitsizer2 = wx.BoxSizer(wx.HORIZONTAL)
		self.unit_type.SetMinSize((127,27))
		self.use_unit.SetMinSize((127,27))
		#self.unit_apply.SetMinSize((127,27))
		showscaletext.SetMinSize((57,27))
		self.show_scale.SetMinSize((62,27))
		self.scale_colorR.SetMinSize((44,27))
		self.scale_colorG.SetMinSize((44,27))
		self.scale_colorB.SetMinSize((44,27))
		unitsizer1.Add(showscaletext, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		unitsizer1.Add(self.show_scale, 0, wx.ADJUST_MINSIZE|wx.LEFT, 1)
		unitsizer2.Add(self.scale_colorR, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.TOP, 0)
		unitsizer2.Add(self.scale_colorG, 0, wx.ADJUST_MINSIZE|wx.TOP, 0)
		unitsizer2.Add(self.scale_colorB, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 0)
		sizer3a = wx.StaticBoxSizer(unitbox,wx.VERTICAL)
		sizer3a.Add(self.unit_type, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3a.Add(self.use_unit, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		#sizer3a.Add(self.unit_apply, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3a.Add(unitsizer1, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3a.Add(unitsizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		multibox = wx.StaticBox(self, -1, 'Layer/Direction')
		self.bias_layer = wx.Choice(self, -1, choices=[])
		self.disp_direc = wx.Choice(self, -1, choices=['Forward','Reverse'])
		self.bias_layer.Disable()
		self.disp_direc.Disable()
		multisizer = wx.BoxSizer(wx.HORIZONTAL)
		self.bias_layer.SetMinSize((127,27))
		self.disp_direc.SetMinSize((127,27))
		sizer3b = wx.StaticBoxSizer(multibox,wx.VERTICAL)
		sizer3b.Add(self.bias_layer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3b.Add(self.disp_direc, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		contbox = wx.StaticBox(self, -1, 'Contours')
		cspace_label = wx.StaticText(self,-1,'N Contours:')
		self.cspace = wx.SpinCtrl(self, -1, '2', min=2, max=50)
		self.showcont = wx.ToggleButton(self, -1, 'Show Contours')
		self.cspace.Disable()
		self.showcont.Disable()
		#self.cspace.Disable()
		#self.showcont.Disable()
		self.showcont.SetMinSize((127,27))
		cspace_label.SetMinSize((79,27))
		self.cspace.SetMinSize((43,27))
		cspacesizer = wx.BoxSizer(wx.HORIZONTAL)
		cspacesizer.Add(cspace_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 10)
		cspacesizer.Add(self.cspace, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		sizer3c = wx.StaticBoxSizer(contbox,wx.VERTICAL)
		sizer3c.Add(cspacesizer, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3c.Add(self.showcont, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		sizer3.Add(sizer3a, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer3b, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer3c, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer3.Add(sizer2g, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer4.Add(sizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer4.Add(sizer3, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		if addlabels != None:
			grid_sizer_1 = wx.FlexGridSizer(1, 3, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer2, 1, wx.GROW, 0)
			grid_sizer_1.Add(addlabels, 1, wx.GROW, 0)
		else:
			grid_sizer_1 = wx.FlexGridSizer(1, 2, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer4, 1, wx.GROW, 0)
		self.SetSizer(grid_sizer_1)
		self.canvas.mpl_connect('motion_notify_event', self.frame.UpdateStatusBar)
		#self.canvas.Bind(wx.EVT_ENTER_WINDOW, self.ChangeCursor)
		self.colors.Bind(wx.EVT_CHOICE, self.OnColor)
		self.interp.Bind(wx.EVT_CHOICE, self.OnInterp)
		self.showhist.Bind(wx.EVT_BUTTON, self.OnHist)
		self.subtr.Bind(wx.EVT_CHOICE, self.OnSubtr)
		self.sgupdate.Bind(wx.EVT_BUTTON, self.OnSGUp)
		self.sgclear.Bind(wx.EVT_BUTTON, self.OnSGClear)
		self.frad.Bind(wx.EVT_SPINCTRL, self.OnFrad)
		self.setrad.Bind(wx.EVT_BUTTON, self.SetFrad)
		self.colinv.Bind(wx.EVT_CHECKBOX, self.OnInv)
		self.applyfft.Bind(wx.EVT_BUTTON, self.OnFFT)
		self.showfft.Bind(wx.EVT_TOGGLEBUTTON,self.OnShowFFT)
		self.filterfft.Bind(wx.EVT_BUTTON,self.OnFilterFFT)
		self.maskfft.Bind(wx.EVT_CHOICE,self.OnMaskSwitch)
		self.clearfilterfft.Bind(wx.EVT_BUTTON,self.OnClearFilterFFT)
		self.selectmaskfft.Bind(wx.EVT_BUTTON,self.OnSelMask)
		self.clearfft.Bind(wx.EVT_BUTTON,self.OnClearFFT)
		self.fftlog.Bind(wx.EVT_CHECKBOX, self.OnFFTLog)
		self.unit_type.Bind(wx.EVT_CHOICE, self.OnUType)
		self.use_unit.Bind(wx.EVT_CHOICE, self.OnUApply)
		self.showcont.Bind(wx.EVT_TOGGLEBUTTON, self.OnShowCont)
		self.disp_direc.Bind(wx.EVT_CHOICE, self.OnDirection)
		self.bias_layer.Bind(wx.EVT_CHOICE, self.OnDirection)
		self.show_scale.Bind(wx.EVT_CHOICE, self.OnShowScale)
		self.scale_colorR.Bind(wx.EVT_CHOICE, self.OnScaleColor)
		self.scale_colorG.Bind(wx.EVT_CHOICE, self.OnScaleColor)
		self.scale_colorB.Bind(wx.EVT_CHOICE, self.OnScaleColor)
		self.displayprop.Bind(wx.EVT_BUTTON, self.OnDispProp)
		self.expimage.Bind(wx.EVT_BUTTON, self.OnExportImage)
		self.displayprop.Disable()
		#self.setrad.Bind(wx.EVT_BUTTON, self.look3D)
		#norm.Bind(wx.EVT_CHOICE, self.OnNorm)
		#self.bkim_box.Bind(wx.EVT_CHOICE, self.OnBackground)
		selprof.Bind(wx.EVT_BUTTON, self.OnProfile)
		#setalpha.Bind(wx.EVT_BUTTON, self.SetAlpha)
	
	def OnDispProp(self,event):
		if hasattr(self,'package'):
			if hasattr(self.package,'SCAN_NUMBER'): namestr = self.package.SCAN_NUMBER
			elif hasattr(self.package, 'SCAN'): namestr = self.package.SCAN
			else: namestr = ''
			ScanProperties(self,self.package,namestr)

	def OnExportImage(self,event):
		if hasattr(self,'package') and hasattr(self.package,'SCAN_NUMBER'):
			fullpath=self.imagepath+str(self.package.SCAN_NUMBER)+'.png'
			count=0
			while os.path.exists(fullpath):
				count+=1
				fullpath=self.imagepath+str(self.package.SCAN_NUMBER)+'_%d.png'%count
			self.figure.savefig( fullpath, format='png' )
			self.editor.InsertImage(fullpath,str(self.package.SCAN_NUMBER))
		else:
			fullpath=self.imagepath+'XXXXXXXXXX'+'.png'
			self.figure.savefig( fullpath, format='png' )
			self.editor.InsertImage(fullpath,'XXXXXXXXXX')

	def OnDirection(self,event):
		if hasattr(self,'data_full'):
			try:
				self.mblayer = self.bias_layer.GetSelection()
				#self.mblayer = int(str(self.bias_layer.GetStringSelection())[-1:])
			except: self.mblayer = 0
			if str(self.disp_direc.GetStringSelection()) == 'Forward':
				self.direc = 0
				self.data = self.data_full[self.mblayer][self.direc]
			else:
				self.direc = 1
				self.data = self.data_full[self.mblayer][self.direc]
			self.display = deepcopy(self.data)
			self.OnSubtr(None)
		else: print 'no data_full attribute'
	
	def OnShowCont(self,event):
		if self.showcont.GetValue():
			ncurves = int(self.cspace.GetValue())
			if ncurves == 1: levels = [self.display.mean()]
			else:
				step = (self.display.max()-self.display.min())/ncurves
				avg = self.display.mean()
				start = avg-(ncurves-1)*(step/2.)-0.01
				end = avg+(ncurves-1)*(step/2.)+0.01
				levels = n.arange(start, end, step)
			self.CS = self.subplot.contour(self.display,levels,origin='lower',linewidths=2,alpha=0.33)
			self.contours = self.subplot.clabel(self.CS,inline=0,fmt='%1.1f',fontsize=12)
		else:
			if hasattr(self,'CS'):
				self.ReDraw(colorbar=False)
		self.canvas.draw()
	
	def ReDraw(self,twin=False,scale=True,colorbar=True):
		self.subplot.clear()
		if not twin: twin=self.showfft.GetValue()
		#if self.extent:
			#self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			#interpolation=self.currinterp)
			#if not twin:
				#self.colorbar = self.figure.colorbar(self.im,shrink=0.8)
				#self.colorbar.draw_all()
				#self.subplot.set_title('Scan No. '+self.SCAN)
		#else:
		self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
		interpolation=self.currinterp)
		self.subplot.set_xlabel('X (Pixels)')
		self.subplot.set_ylabel('Y (Pixels)')
		if not twin:
			if colorbar:
				self.colorbar = self.figure.colorbar(self.im,shrink=0.8)
				self.colorbar.draw_all()
			self.subplot.set_title('Scan No. '+self.SCAN)
			self.scalebar=[None,None]
		if scale: self.MakeScaleBar()
	
	def OnUType(self,event):
		unit = str(self.unit_type.GetStringSelection())
		if unit == 'XY' or unit == 'Z':
			self.use_unit.SetItems(self.dist_unit)
		elif unit == 'I':
			self.use_unit.SetItems(self.current_unit)
	
	def OnUApply(self,event):
		unittype = str(self.unit_type.GetStringSelection())
		unit = str(self.use_unit.GetStringSelection())
		if unittype == 'XY':
			self.xyunit = unit
			self.MakeScaleBar()
		elif unittype == 'Z':
			self.zunit = unit
			self.OnSubtr(None)
		elif unittype == 'I': self.iunit = unit
		#self.OnSubtr(None)
		
	
	def addToNotebook(self,title):
		self.parent.AddPage(self,title)
		self.SCAN = title
		self.parent.SetSelection(self.pagenum)
	
	def delFromNotebook(self):
		self.parent.RemovePage(self.pagenum)
		
	def subtr1Line(self,line):
		X = n.zeros(line.shape)
		X[:] = range(len(line[0]))
		a,b = self.linreg(X,line)
		subtr = n.add(n.multiply(X[0],a[0]),b[0])
		line2 = n.subtract(copy(line),subtr)
		return line2
	
	def linreg(self, X1, Y1, image=False):
		"""
		Takes two matricies and finds the slope and intercept of each line
		along axis 1.
		
		Returns 2 arrays. b is the array of intercepts and a
		is the array of slopes.
		"""
		if X1.shape != Y1.shape:  raise ValueError, 'unequal length'
		if not image:
			X = X1[::5]
			Y = Y1[::5]
		else:
			X = X1
			Y = Y1
		N = len(X[0])
		Sx = Sy = Sxx = Syy = Sxy = n.zeros(N)
		Sx = n.sum(X,axis=1)
		Sy = n.sum(Y,axis=1)
		Sxx = n.sum(n.square(X),axis=1)
		Syy = n.sum(n.square(Y),axis=1)
		
		Sxy = n.sum(n.multiply(X,Y),axis=1)
		det = n.subtract(n.multiply(Sxx,N),n.square(Sx))
		a, b = n.divide(n.subtract(n.multiply(Sxy,N),n.multiply(Sy,Sx)),det),\
		n.divide(n.subtract(n.multiply(Sxx,Sy),n.multiply(Sx,Sxy)),det)
		return a,b
	
	def subtr1Plane(self,line,lineN):
		X = n.zeros(line.shape)
		X[:] = range(len(line[0]))
		
		subtr = n.multiply(X[0],self.ax)+lineN*self.ay
		line2 = n.subtract(copy(line),subtr)-self.pave
		return line2
	
	def savgolXLine(self,line):
		data2 = n.zeros(line.shape)
		data2 = n.array([sg.smooth(copy(line[0]),self.coeff)])
		return data2
	
	def subtrImageLines(self,data):
		fits = []
		X = n.zeros(n.shape(data))
		for i in range(n.shape(data)[1]):
			X[:,i] = i
		Y = data
		fits = self.linreg(X,Y,image=True)
		subtr = n.transpose(n.add(n.multiply(n.transpose(X),fits[0]),fits[1]))
		data2 = n.subtract(data,subtr)
		return data2
		
	def subtrImagePlane(self,data1,lineN):
		data = deepcopy(data1)[0:lineN,:]
		Xx = n.zeros(n.shape(data))
		for i in range(n.shape(data)[1]):
			Xx[:,i] = i
		Yx = data
		ax,bx = self.linreg(Xx,Yx,image=True)

		Xy = n.zeros(n.shape(data))
		for i in range(n.shape(data)[0]):
			Xy[i,:] = i
		Yy = data
		ay,by = self.linreg(n.transpose(Xy),n.transpose(Yy),image=True)
		self.ax = n.average(ax)
		self.ay = n.average(ay)
		subtrx = n.multiply(Xx,self.ax)
		subtry = n.multiply(Xy,self.ay)
		subtr = n.add(subtrx,subtry)
		sdata = n.subtract(deepcopy(data),subtr)
		self.pave = n.average(sdata)
		sdata = n.subtract(sdata,self.pave)
		rdata = n.zeros(data1.shape)
		rdata[0:lineN,:] = sdata
		return rdata
	
	def savgolX(self,data):
		data2 = n.zeros(data.shape)
		if self.sgderiv > self.polyorder:
			self.porder.SetValue(int(self.sgderiv))
			self.polyorder = self.sgderiv
		self.coeff = sg.calc_coeff(self.gradpts, self.polyorder, self.sgderiv)
		for i in range(data.shape[0]): data2[i] = sg.smooth(data[i],self.coeff)
		return data2
	
	def FFT2d(self,data):
		pad=int(self.padval.GetValue())
		window=self.windowfft.GetStringSelection()
		if window=='hanning':
			windvals=(n.resize(n.hanning(data.shape[0]),(data.shape[0],1))*n.resize(n.hanning(data.shape[1]),(1,data.shape[1])))
		elif window=='hamming':
			windvals=(n.resize(n.hamming(data.shape[0]),(data.shape[0],1))*n.resize(n.hamming(data.shape[1]),(1,data.shape[1])))
		elif window=='blackman':
			windvals=(n.resize(n.blackman(data.shape[0]),(data.shape[0],1))*n.resize(n.blackman(data.shape[1]),(1,data.shape[1])))
		elif window=='kaiser':
			windvals=(n.resize(n.kaiser(data.shape[0],beta=0),(data.shape[0],1))*n.resize(n.kaiser(data.shape[1],beta=0),(1,data.shape[1])))
		elif window=='bartlett':
			windvals=(n.resize(n.bartlett(data.shape[0]),(data.shape[0],1))*n.resize(n.bartlett(data.shape[1]),(1,data.shape[1])))
		else: windvals=n.ones(data.shape)
		fft_data = n.fft.fft2(windvals*deepcopy(data),s=(data.shape[0]+pad,data.shape[1]+pad))
		self.fft_raw=n.roll(n.roll(fft_data,(data.shape[0]+pad)/2,axis=0),(data.shape[1]+pad)/2,axis=1)
		fft_mod = n.sqrt(n.real(fft_data)**2+n.imag(fft_data)**2)
		fft_roll = n.roll(n.roll(fft_mod,(data.shape[0]+pad)/2,axis=0),(data.shape[1]+pad)/2,axis=1)
		if self.fftlog.GetValue():
			fft_roll += 0.0001*(fft_roll.max()-fft_roll.min())
			return n.log(fft_roll)
		else: return fft_roll
	
	
	def displayConvert(self,data,image=False):
		subtype = str(self.subtr.GetStringSelection())
		if not image:
			if subtype == 'None' or subtype == '--Subtraction--': data2 = data
			elif subtype == 'Line': data2 = self.subtr1Line(deepcopy(data))
			elif subtype == 'Plane': data2 = self.subtr1Plane(deepcopy(data),self.lineN)
			else: data2 = data
		else:
			if subtype == 'None' or subtype == '--Subtraction--': data2 = data
			elif subtype == 'Line': data2 = self.subtrImageLines(deepcopy(data))
			elif subtype == 'Plane': data2 = self.subtrImagePlane(deepcopy(data),self.lineN)
			else: data2 = data
		if hasattr(self,'UO'):
			unit_type=self.unit_type.GetStringSelection()
			if unit_type=='Z':
				if hasattr(self,'package'):
					data2 = self.UO._ConvertZScale(data2,self.UO.ZVOLTS,self.UO.units[self.zunit][0],self.package.GAIN_ZHV[0],self.package.GAIN_ZOUT[0])
				else:
					data2 = self.UO._ConvertZScale(data2,self.UO.ZVOLTS,self.UO.units[self.zunit][0],self.ZHV,self.ZOUT)
			elif unit_type=='XY' and hasattr(self,'package'):
				if not hasattr(self,'scalebar') or self.scalebar[0] == None:
					self.MakeScaleBar()
		return data2
	
	def OnShowScale(self,event,draw=True):
		alpha=self.show_scale.GetStringSelection()
		if hasattr(self.scalebar[1],'set_alpha'): self.scalebar[1].set_alpha(float(alpha)/100.)
		if hasattr(self.scalebar[0],'set_alpha'): self.scalebar[0].set_alpha(float(alpha)/100.)
		if draw: self.canvas.draw()
		self.scale_trans=float(alpha)/100.
	
	def OnScaleColor(self,event,draw=True):
		colorR=self.scale_colorR.GetStringSelection()
		colorG=self.scale_colorG.GetStringSelection()
		colorB=self.scale_colorB.GetStringSelection()
		if colorR[0]=='R': colorR='0'
		if colorG[0]=='G': colorG='0'
		if colorB[0]=='B': colorB='0'
		color='#'+2*colorR+2*colorG+2*colorB
		if hasattr(self.scalebar[1],'set_color'): self.scalebar[1].set_color(color)
		if hasattr(self.scalebar[0],'set_color'): self.scalebar[0].set_color(color)
		if draw: self.canvas.draw()

	def MakeScaleBar(self):
		if hasattr(self,'package'):
			xext,yext=self.UO._ConvertPixels(self.data.shape[0],self.data.shape[1],self.package.DAC_STEP[0]*self.package.DAC_AVGS[0],\
			self.UO.units[self.xyunit][0],self.package.GAIN_XHV[0],self.package.GAIN_YHV[0])
		elif hasattr(self,'DAC_STEP'):
			xext,yext=self.UO._ConvertPixels(self.data.shape[0],self.data.shape[1],self.DAC_STEP[0]*self.DAC_AVGS[0],\
			self.UO.units[self.xyunit][0],1,1)
		else: yext,xext = self.data.shape
		self.extents=(xext,yext)
		if not self.scalebar[1] == None:
			self.scalebar[1].set_text('%.2f %s'%((self.extents[0]/5.),self.UO.units[self.xyunit][1]))
		else:
			self.scalebar[0]=self.subplot.axhline(y=int(self.data.shape[1]*0.1), xmin=0.05, xmax=0.25,linewidth=4, color='r')
			self.scalebar[1]=self.subplot.text(int(self.data.shape[0]*0.22/2),int(self.data.shape[1]*0.075),'%.2f %s'%((self.extents[0]/5.),\
			self.UO.units[self.xyunit][1]), fontsize=16, color='r')
		#self.scalebar[0].set_alpha(0)
		self.OnShowScale(None,draw=False)
		self.OnScaleColor(None,draw=False)
		self.canvas.draw()

	def OnSubtr(self, event):
		data = self.displayConvert(self.data,image=True)
		self.display = data
		self.im.set_data(self.display)
		self.AutoAdjust()
		#self.im.set_extent(self.extent)
		self.canvas.draw()
	
	def OnShowFFT(self, event):
		if self.showfft.GetValue():
			self.figure.clf()
			self.subplot = self.figure.add_subplot(121)
			self.ReDraw(twin=True)
			self.canvas.draw()
			self.OnSubtr(event)
			self.AutoAdjust()
			self.subplotfft=self.figure.add_subplot(122)
			self.canvas.draw()
			self.OnFFT(event)
			self.filterfft.Enable()
			self.filterpix.Enable()
			self.selectmaskfft.Enable()
			self.maskfft.Enable()
		else:
			self.filterfft.Disable()
			self.filterpix.Disable()
			self.selectmaskfft.Disable()
			self.maskfft.Disable()
			self.figure.clf()
			self.subplot = self.figure.add_subplot(111)
			#self.OnFFT(event)
			self.ReDraw()
			self.canvas.draw()
		self.fftmask=n.zeros(self.fft_raw.shape)
	
	def OnClearFFT(self, event):
		if self.showfft.GetValue(): pass
		else:
			self.OnSubtr(event)
			self.ReDraw(colorbar=False)
			self.canvas.draw()
	
	def OnSelMask(self,event):
		if self.showfft.GetValue():
			self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_QUESTION_ARROW))
			self.canvas.Bind(wx.EVT_LEFT_DOWN, self.MaskFFT)
	
	def OnMaskSwitch(self,event):
		masktype=self.maskfft.GetStringSelection()
		if masktype=='Square': self.fftmask[:,:]=1
		elif masktype=='4-Fold': self.fftmask[:,:]=1
		elif masktype=='4-Fold Inverse': self.fftmask[:,:]=0
		elif masktype=='6-Fold': self.fftmask[:,:]=1
		elif masktype=='6-Fold Inverse': self.fftmask[:,:]=0

	def SqrMask(self,xloc,yloc,pix,inv=False):
		if not inv: self.fftmask[yloc-pix/2:yloc+pix/2,xloc-pix/2:xloc+pix/2]=0
		else: self.fftmask[yloc-pix/2:yloc+pix/2,xloc-pix/2:xloc+pix/2]=1
		el = matplotlib.patches.Rectangle((xloc-pix/2, yloc-pix/2), pix, pix,facecolor='w',edgecolor='w')
		self.subplotfft.add_patch(el)
		el.set_alpha(0.25)

	def MaskFFT(self,event):
		self.canvas.Bind(wx.EVT_LEFT_DOWN, None)
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		xloc = int(round(self.frame.x))
		yloc = int(round(self.frame.y))
		pix=int(self.filterpix.GetValue())
		masktype=self.maskfft.GetStringSelection()
		if masktype=='Square': self.SqrMask(xloc,yloc,pix)
		elif masktype=='4-Fold':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			self.SqrMask(cx+dx,cy+dy,pix)
			self.SqrMask(cx-dx,cy-dy,pix)
			self.SqrMask(cx-dy,cy+dx,pix)
			self.SqrMask(cx+dy,cy-dx,pix)
		elif masktype=='4-Fold Inverse':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			self.SqrMask(cx+dx,cy+dy,pix,inv=True)
			self.SqrMask(cx-dx,cy-dy,pix,inv=True)
			self.SqrMask(cx-dy,cy+dx,pix,inv=True)
			self.SqrMask(cx+dy,cy-dx,pix,inv=True)
		elif masktype=='6-Fold':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			a1=n.sin(60*n.pi/180)
			a2=n.sin(30*n.pi/180)
			self.SqrMask(cx+dx,cy+dy,pix)
			self.SqrMask(cx-dx,cy-dy,pix)
			self.SqrMask(cx+(a2*dx-a1*dy),cy+(a1*dx+a2*dy),pix)
			self.SqrMask(cx-(a2*dx-a1*dy),cy-(a1*dx+a2*dy),pix)
			self.SqrMask(cx+(a2*dx+a1*dy),cy-(a1*dx-a2*dy),pix)
			self.SqrMask(cx-(a2*dx+a1*dy),cy+(a1*dx-a2*dy),pix)
		elif masktype=='6-Fold Inverse':
			dx=xloc-self.fft_raw.shape[0]/2
			dy=yloc-self.fft_raw.shape[1]/2
			cx=self.fft_raw.shape[0]/2
			cy=self.fft_raw.shape[1]/2
			a1=n.sin(60*n.pi/180)
			a2=n.sin(30*n.pi/180)
			self.SqrMask(cx+dx,cy+dy,pix,inv=True)
			self.SqrMask(cx-dx,cy-dy,pix,inv=True)
			self.SqrMask(cx+(a2*dx-a1*dy),cy+(a1*dx+a2*dy),pix,inv=True)
			self.SqrMask(cx-(a2*dx-a1*dy),cy-(a1*dx+a2*dy),pix,inv=True)
			self.SqrMask(cx+(a2*dx+a1*dy),cy-(a1*dx-a2*dy),pix,inv=True)
			self.SqrMask(cx-(a2*dx+a1*dy),cy+(a1*dx-a2*dy),pix,inv=True)
		self.canvas.draw()
	
	def OnFilterFFT(self,event):
		# Re-display Masked Fourier Transform
		#fft_mod = n.sqrt(n.real(self.fft_raw)**2+n.imag(self.fft_raw)**2)
		#if self.fftlog.GetValue():
			#fft_mod += 0.0001*(fft_mod.max()-fft_mod.min())
			#fft_mod=n.log(fft_mod)
		#self.imfft.set_data(fft_mod)

		fft_roll = n.roll(n.roll(self.fftmask*self.fft_raw,(self.fft_raw.shape[0])/2,axis=0),(self.fft_raw.shape[1])/2,axis=1)
		fft_data=n.fft.ifft2(deepcopy(fft_roll),s=(fft_roll.shape[0],fft_roll.shape[1]))
		fft_mod = n.real(fft_data)
		self.display= fft_mod
		self.ReDraw(twin=True)
		self.canvas.draw()
	
	def OnClearFilterFFT(self,event):
		self.OnMaskSwitch(None)
		#self.OnSubtr(event)
		self.ReDraw(colorbar=False)
		if self.showfft.GetValue(): self.OnFFT(event)
	
	def OnMaskFFT(self,event): pass

	def OnFFT(self, event,log=False):
		#if self.applyfft.GetValue():
		if self.showfft.GetValue():
			#twin view on
			self.subplotfft.clear()
			fftdisplay = self.FFT2d(self.display)
			self.imfft=self.subplotfft.imshow(fftdisplay,origin='lower')
			self.canvas.draw()
		else:
			#twin view off
			self.display = self.FFT2d(self.display)
			if event.GetId() == self.APPLY_ID or log: self.ReDraw(scale=False,colorbar=False)
			else: self.ReDraw(scale=False)
			self.canvas.draw()
		#else: self.OnSubtr(event)
	
	def OnFFTLog(self, event):
		#if self.applyfft.GetValue():
		data = self.displayConvert(self.data,image=True)
		self.display = data
		self.OnFFT(event,log=True)
		#else: pass
	
	def OnInv(self, event):
		color = self.colors.GetStringSelection()
		self.OnColor(event,color=color)
	
	def OnProfile(self, event):
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_QUESTION_ARROW))
		self.canvas.Bind(wx.EVT_LEFT_DOWN, self.MakeProfile)
	
	def OnSGUp(self, event):
		self.gradpts = int(self.sgpts.GetValue())
		self.polyorder = int(self.porder.GetValue())
		self.sgderiv = int(self.dorder.GetValue())
		data2 = self.savgolX(deepcopy(self.data))
		data=self.displayConvert(data2,image=True)
		self.display=data
		self.im.set_data(self.display)
		self.AutoAdjust()
		self.canvas.draw()
	
	def OnSGClear(self, event):
		self.OnSubtr(event)

	def MakeProfile(self, event):
		xloc = int(round(self.frame.x))
		yloc = int(round(self.frame.y))
		self.canvas.Bind(wx.EVT_LEFT_DOWN, None)
		if not hasattr(self,'extents'):
			self.MakeScaleBar()
		if str(self.prof_box.GetStringSelection()) == 'Vertical':
			if xloc > len(self.display[:,xloc]): pass
			else:
				#self.xline = self.im.axes.axvline(x=xloc,figure=self.figure)
				title = 'Vertical Profile at x=%d'%xloc
				LineProfile(self,title,self.display[:,xloc],self.zunit,float(self.extents[1])/self.data.shape[0],self.UO.units[self.xyunit][1],xory='X')
			self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		elif str(self.prof_box.GetStringSelection()) == 'Horizontal':
			
			#self.yline = self.im.axes.axhline(y=yloc,figure=self.figure)
			title = 'Horizontal Profile at y=%d'%yloc
			LineProfile(self,title,self.display[yloc,:],self.zunit,float(self.extents[0])/self.data.shape[1],self.UO.units[self.xyunit][1],xory='Y')
			self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		elif str(self.prof_box.GetStringSelection()) == 'Arbitrary':
			self.lastx = xloc
			self.lasty = yloc
			self.canvas.Bind(wx.EVT_LEFT_DOWN, self.MakeArb)
		self.canvas.draw()
	
	def MakeArb(self, event):
		self.canvas.Bind(wx.EVT_LEFT_DOWN, None)
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		xloc = int(round(self.frame.x))
		yloc = int(round(self.frame.y))
		nx = xloc-self.lastx
		ny = yloc-self.lasty
		if nx == 0:
			a = [self.lasty,yloc]
			a.sort()
			z = self.display[a[0]:a[1],xloc]
			if self.lasty > yloc: z = n.flipud(z)
		elif ny == 0:
			a = [self.lastx,xloc]
			a.sort()
			z = self.display[yloc,a[0]:a[1]]
			if self.lastx > xloc: z = n.flipud(z)
		else:
			m = ny/float(nx)
			b = self.lasty-m*self.lastx
			num = n.sqrt(n.square(nx)+n.square(ny))
			x = n.arange(self.lastx,int(round(self.frame.x)),nx/float(num))
			y = m*x+b
			z = []
			for i in range(len(x)): z.append(self.ZInterp(self.display,x[i],y[i]))
		title = 'Arbitrary Profile from (%d,%d) to (%d,%d)'%(self.lastx,self.lasty,xloc,yloc)
		if hasattr(self.subplot,'arrow'):
			#if hasattr(self,'proline'): self.proline.remove()
			self.proline = self.subplot.arrow(self.lastx,self.lasty,nx,ny,axes=self.subplot,ec='green', fc='green',lw=2,alpha=0.5,head_width=1,head_length=1)
			self.canvas.draw()
		LineProfile(self,title,n.array(z),self.zunit,n.sqrt(((float(self.extents[0])/self.data.shape[0])*nx)**2+((float(self.extents[0])/self.data.shape[0])*ny)**2)/len(z),self.UO.units[self.xyunit][1],xory='A')

	
	def ZInterp(self,data,x,y):
		x0 = int(n.floor(x))
		y0 = int(n.floor(y))
		x1 = int(n.ceil(x))
		y1 = int(n.ceil(y))
		z00 = data[y0,x0]
		z11 = data[y1,x1]
		z10 = data[y0,x1]
		z01 = data[y1,x0]
		if x-x0 == 0: t = 0
		elif x-x1 == 0: t=1
		else: t = (x-x0)/float(x1-x0)
		if y-y0 == 0: u = 0
		elif y-y1 == 0: u=1
		else: u = (y-y0)/float(y1-y0)
		z = (1-t)*(1-u)*z00 + t*(1-u)*z10 + t*u*z11 + (1-t)*u*z01
		return z
	
	def look3D(self, event):
		Plot3D(self, self.display)
	
	def AutoAdjust(self):
		zmax = n.mean(self.display)+2*n.std(self.display)
		zmin = n.mean(self.display)-2*n.std(self.display)
		self.SetLim(zmin=zmin,zmax=zmax)
		
	def add_line(self,data,lineN):
		self.lineN = lineN
		self.data[lineN,:] = data
		self.display[lineN,:] = self.displayConvert(data) 
		self.gauge.SetValue(lineN)
		if lineN == self.shape[0]-1: self.timer.Stop()
		elif not lineN ==self.shape[0]-1 and not self.timer.IsRunning(): self.timer.Start(1000)
		if lineN == 1 or not self.im:
			#self.subplot.hold(True)
			zmin = n.min(self.display)
			zmax = n.max(self.display)
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp,vmin=zmin,vmax=zmax)
			self.colorbar.set_clim(vmin=zmin,vmax=zmax)
			self.colorbar.draw_all()
			#self.subplot.hold(True)
			self.canvas.draw()
		elif lineN%25==0:
			#zmin = n.min(self.data)
			#zmax = n.max(self.data)
			#self.colorbar.set_clim(vmin=zmin,vmax=zmax)
			#self.colorbar.draw_all()
			self.canvas.draw()
		else: self.im.set_data(self.display)
		#self.im.set_data(self.data)
	
	def ElapsedTime(self,event):
		#timeleft = ((time.time()-self.starttime)/lineN)*self.shape[0]
		if self.timer.IsRunning() and not len(self.frame.pages.keys()) == self.pagenum+1: self.timer.Stop()
		else:
			elapsed = time.time()-self.starttime
			minutes = str(int(elapsed)/60)
			seconds = str(int(elapsed)%60)
			if len(seconds)==1: seconds = '0'+seconds
			self.elapsedtime.SetLabel('Elapsed: %s min %s s'%(minutes,seconds))
	
	def Update(self,data,lineN,noline=False):
		if not noline: self.add_line(data,lineN) # Add the line to the data
	
		if hasattr(self, 'lastTime') and (1./(time.time()-self.lastTime)) < self.fps: #check if the max fps is being exceeded
			self.subplot.draw_artist(self.im)
			if self.bkim != None: self.bkim.figure.canvas.blit()
			if self.transspec != None:
				self.subplot.draw_artist(self.mask)
				self.mask.figure.canvas.blit()
			#if  'canvas' in dir(self.im.figure) and 'blit' in dir(self.im.figure.canvas):
			if  hasattr(self.im.figure,'canvas') and hasattr(self.im.figure.canvas,'blit'):
				self.im.figure.canvas.blit()
			else:
				self.canvas.draw()
			self.lastTime = time.time()
		elif not hasattr(self, 'lastTime'): self.lastTime = time.time()
		else: pass
		
	def ChangeCursor(self, event):
		self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
	
	def onselect(self,eclick,erelease):
		self.canvas.draw()
		x0,y0,x1,y1 = [eclick.xdata, eclick.ydata,erelease.xdata, erelease.ydata]
		if eclick.button == 1:
			self.writeRect(x0,y0,x1,y1)
		else:
			self.eraseRect(x0,y0,x1,y1)
		self.frame.specq.put(self.spec_mask)
		self.dispSpec(self.spec_mask,update=True)
	
	def sortCoord(self,x0,y0,x1,y1):
		list1 = [x0,x1]
		list2 = [y0,y1]
		list1.sort()
		list2.sort()
		return list1[0],list2[0],list1[1],list2[1]
	
	def writeRect(self,x0,y0,x1,y1):
		(xx,yx,xy,yy) = self.sortCoord(x0,y0,x1,y1)
		if yx <= self.lineN: yx = self.lineN
		else: pass
		gridx = self.GRIDX
		gridy = self.GRIDY
		if self.checker:
			self.spec_mask[yx:yy,xx:xy][::2*gridy,::gridx] = 1
			self.spec_mask[yx:yy,xx:xy][gridy::2*gridy,int(gridx/2.)::gridx] = 1
		else:
			self.spec_mask[yx:yy,xx:xy][::gridy,::gridx] = 1
		return self.spec_mask
	
	def eraseRect(self,x0,y0,x1,y1):
		(xx,yx,xy,yy) = self.sortCoord(x0,y0,x1,y1)
		if yx <= self.lineN: self.yx = self.lineN
		else: pass
		self.spec_mask[yx:yy,xx:xy] = 0
		return self.spec_mask
	
	def OnColor(self, event,color=None):
		if color == None: color = event.GetString()
		if color in self.cmap:
			if self.colinv.GetValue(): self.currcmap = self.cmap_r[color]
			else: self.currcmap = self.cmap[color]
			self.im.set_cmap(self.currcmap)
			self.colorbar.set_cmap(self.currcmap)
			self.colorbar.draw_all()
			self.canvas.draw()
		elif self.colors.GetSelection() == 0 and self.colinv.GetValue():
			self.currcmap = self.cmap_r[ws.DEFAULT_CMAP]
			self.im.set_cmap(self.currcmap)
			self.colorbar.set_cmap(self.currcmap)
			self.colorbar.draw_all()
			self.canvas.draw()
		else: pass
	
	def OnInterp(self, event):
		interp = event.GetString()
		if interp != self.interps[0]:
			self.currinterp = interp
			self.im.set_interpolation(interp)
			self.canvas.draw()
		else: pass
	
	def OnBackground(self, event):
		if event.GetString() == 'None': self.bkim = None
		else:
			self.bkim = self.subplot.imshow(copy(self.frame.pages[event.GetString()].display),origin='lower',\
				cmap=self.currcmap,interpolation=self.currinterp)
			self.bkim.figure.canvas.blit()
		self.im.figure.canvas.blit()
		self.canvas.draw()
	
	def OnHist(self, event):
		asdf = MakeHist(self,'Histogram '+self.SCAN,self.display)
	
	def SetFrad(self, event):
		frad = float(self.pix.GetLabel())
		self.im.set_filterrad(frad)
		self.currfrad = frad
		self.canvas.draw()
	
	def SetAlpha(self, event):
		alpha = int(self.alpha.GetValue())/10.
		self.im.set_alpha(alpha)
		self.canvas.draw()
		self.curralpha = alpha
	
	def OnFrad(self, event):
		frad = str(self.frad.GetValue())
		self.pix.SetLabel(str(int(frad)/10.))
	
	def OnNorm(self,event):
		norm = event.GetString()
		if norm =='yes':
			self.im.set_filternorm(1)
		elif norm =='no':
			self.im.set_filternorm(0)
		self.canvas.draw()
	
	def toggle_selector(self, event):
		pass
		#self.span.set_active(not self.span.get_active())
	
	def toggle_mask(self, event):
		self.subplot.clear()
		if self.mask == None:
			cmap=cm.spring
			cmap.set_bad((0,0,0),alpha=1)
			self.mask = self.subplot.pcolor(self.transspec,alpha=0.9,cmap=cmap,\
			vmin=0,vmax=1)
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			#self.im.figure.canvas.blit()
			#self.mask.figure.canvas.blit()
			self.canvas.draw()
		else:
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.mask = None
			self.canvas.draw()
	
	def toggle_spec(self, event):
		self.makeSpec()
	
	def dispSpec(self, data,update=False):
		if data.any():
			#self.ax = self.parent.canvas.figure.axes[0]
			#self.a = self.figure.add_subplot(111)
			self.spec_mask = data
			if self.transspec == None or update:
				mask = (~n.uint8(deepcopy(data)))-254
				self.transspec = nx.ma.masked_array(n.zeros(data.shape),mask=mask)
			else: pass
			if update:
				cmap = cm.spring
				cmap.set_bad((0,0,0),alpha=1)
				self.subplot.clear()
				self.mask = self.subplot.pcolor(self.transspec,alpha=0.7,cmap=cmap)
				self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
				interpolation=self.currinterp)
				#if 'canvas' in dir(self.im.figure) and 'blit' in dir(self.im.figure.canvas):
				if  hasattr(self.im.figure,'canvas') and hasattr(self.im.figure.canvas,'blit'):
					self.im.figure.canvas.blit()
					self.mask.figure.canvas.blit()
				else:
					self.canvas.draw()
			else:
				cmap=cm.spring
				cmap.set_bad((0,0,0),alpha=1)
				#self.subplot.hold(True)
				self.subplot.clear()
				self.mask = self.subplot.pcolor(self.transspec,alpha=0.7,cmap=cmap)
				self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
				interpolation=self.currinterp)
				zmin = n.min(self.data)
				zmax = n.max(self.data)
				self.colorbar.set_clim(vmin=zmin,vmax=zmax)
				self.colorbar.draw_all()
				self.canvas.draw()
	
	def SetLim(self,zmax=None,zmin=None):
		if zmax != None and zmin != None: pass
			#if not zmax > zmin: zmax = zmin + 0.01*abs(zmin)
		elif zmax == None: temp,zmax = self.im.get_clim()
		elif zmin == None: zmin,temp = self.im.get_clim()
		self.colorbar.set_clim(vmax=zmax,vmin=zmin)
		self.im.set_clim(vmax=zmax,vmin=zmin)
		#if zmax != None:
			#self.colorbar.set_clim(vmax=zmax)
			#self.im.set_clim(vmax=zmax)
		#if zmin != None:
			#self.colorbar.set_clim(vmin=zmin)
			#self.im.set_clim(vmin=zmin)
		self.subplot.draw_artist(self.im)
		self.colorbar.draw_all()
		self.canvas.draw()
	
	def SingleDisable(self):
		self.subtr.Disable()
		self.frad.Disable()
		self.pix.Disable()
		self.colors.Disable()
		self.interp.Disable()
		self.showhist.Disable()
		self.setrad.Disable()
	
	def CompEnable(self):
		self.showcont.Enable()
		self.disp_direc.Enable()
		self.show_scale.Enable()
		self.cspace.Enable()

	def _set_complete(self,fulldata):
		self.timer.Stop()
		self.package = fulldata
		self.displayprop.Enable()
		if hasattr(self.package,'IMAGEDATA'):
			#zout = self.package.GAIN_ZOUT[0]*10+1
			#self.ZSCALE = self.package.GAIN_ZHV[0]/zout
			self.data = self.package.IMAGEDATA[0][ws.DISPLAY_DIR]
			self.data_full = self.package.IMAGEDATA
			self.CompEnable()
			biases = []
			if hasattr(self.package,'N_BIAS_STEPS'):
				for i in range(self.package.N_BIAS_STEPS[0]+1):
					sampbias=str(self.package.SAMPLE_BIAS[0]+self.package.BIAS_STEPS[i][0]).split('.')
					sampbias = str(sampbias[0]+'.'+sampbias[1][0:2])
					biases.append(sampbias+' V')
			else:
				sampbias=str(self.package.SAMPLE_BIAS[0]).split('.')
				sampbias = str(sampbias[0]+'.'+sampbias[1][0:2])
				biases.append(sampbias+' V')
			layers = []
			for i in range(len(self.data_full)): layers.append('layer%d, %s'%(i,biases[i]))
			self.bias_layer.SetItems(layers)
			if len(layers) > 0: self.bias_layer.Enable()
			self.display = self.displayConvert(self.data,image=True)
			self.TYPE = self.package.TYPE
			self.im = self.subplot.imshow(self.display,origin='lower',cmap=self.currcmap,\
			interpolation=self.currinterp)
			self.subtr.SetStringSelection('Line')
			self.OnSubtr(None)
			zmax = n.mean(self.display)+2*n.std(self.display)
			zmin = n.mean(self.display)-2*n.std(self.display)
			self.SetLim(zmax=zmax,zmin=zmin)
			if self.TYPE in self.frame.imagespec:
				self.toolbar._addSpecToggle()
				self.toolbar._addMaskToggle()
				self.dispSpec(self.package.SPEC_MASK)
				self.coords = str((0,0))
				self.spec_index = 1
				self.specsub = None
				self.pcolor_curr = None
				self.canvas.Bind(wx.EVT_KEY_DOWN, self.MoveSpec)
				self.getSpecPos()
			
			if hasattr(self.package,'iSPEC'):
				self.SPEC_DATA = self.package.iSPEC
			elif self.TYPE == 'imagewiv':
				self.SPEC_DATA = self.package.IV
			elif self.TYPE == 'imagewiz':
				self.SPEC_DATA = self.package.IZ
			elif self.TYPE == 'imagewzv':
				self.SPEC_DATA = self.package.ZV
		elif hasattr(self.package,'iSPEC'):
			self.subplot.clear()
			coords = str((0,0))
			asdf = SpecFigure(self,'name',external=[self,self.figure,self.canvas]\
			,spec_type = self.package.spec_type,toolbar=self.toolbar)
			asdf._drawOnChange(coords,self.package.iSPEC[self.package.iSPEC.keys()[0]])
			self.SingleDisable()
		
		
	#def refreshSpec(self,event):
		#self.setPlot(copy(self.data))
		#spec_mask = copy(self.dic['SPEC_MASK'])
		#mask = (~n.uint8(spec_mask))-254
		#self.spec_over = nx.ma.masked_array(n.zeros(spec_mask.shape),mask=mask)
		#cmap=cm.jet
		#cmap.set_bad((0,0,0),alpha=1)
		#self.subplot1.pcolor(self.spec_over,alpha=0.5,cmap=cmap)
		#self.canvas1.draw()
		#self.canvas1.SetFocus()
	
	def currentSpec(self,yloc,xloc):
		spec_mask = n.zeros(self.data.shape)
		spec_mask[yloc,xloc] = 1
		mask = (~n.uint8(spec_mask))-254
		self.spec_over = nx.ma.masked_array(n.zeros(spec_mask.shape),mask=mask)
		cmap=cm.gray_r
		cmap.set_bad((0,0,0),alpha=1)
		if not self.pcolor_curr:
			self.pcolor_curr = self.subplot.pcolor(self.spec_over,alpha=0.5,cmap=cmap)
		else:
			self.pcolor_curr = self.subplot.pcolor(self.spec_over,alpha=0.75,cmap=cmap)
		self.canvas.draw()
	
	def getSpecPos(self):
		self.locations = copy(n.uint8(self.package.SPEC_MASK)).nonzero()
		temp_mask = n.uint8(self.package.SPEC_MASK)
		lst = []
		for i in range(len(temp_mask)):
			lst.append(temp_mask[i].nonzero()[0])
		lst2 = []
		for i in range(len(lst)):
			lst2.append(len(lst[i]))
		self.udmove = lst2

	
	def MoveSpec(self, event):
		if self.TYPE in self.frame.imagespec and not self.specsub==None:
			KEY_PRESSED = event.GetKeyCode()
			sum = 0
			count = 0
			if KEY_PRESSED == wx.WXK_LEFT:
				self.spec_index -= 1
			elif KEY_PRESSED == wx.WXK_RIGHT:
				self.spec_index += 1
			elif KEY_PRESSED == wx.WXK_UP:
				while sum < self.spec_index:
					sum += self.udmove[count]
					count += 1
				self.spec_index += self.udmove[count-1]
			elif KEY_PRESSED == wx.WXK_DOWN:
				while sum < self.spec_index:
					sum += self.udmove[count]
					count += 1
				self.spec_index -= self.udmove[count-1]
			if self.spec_index < 0: self.spec_index = len(self.locations[0])-1
			elif self.spec_index > len(self.locations[0])-1: self.spec_index = 0
			xloc = int(self.locations[1][self.spec_index])
			yloc = int(self.locations[0][self.spec_index])
			self.currentSpec(yloc,xloc)
			self.x = str(xloc)
			self.y = str(yloc)
			self.coords = str((int(self.y),int(self.x)))
			if self.coords in self.SPEC_DATA.keys():
				self.specsub._drawOnChange(self.coords,self.SPEC_DATA[self.coords])
		elif self.TYPE in self.frame.imagespec and self.specsub == None: self.makeSpec()
	
	def makeSpec(self):
		if not self.specsub and self.TYPE == 'imagewiv':
			self.specsub = SpecFigure(self,self.package.NAME[0] + ' IV')
		elif not self.specsub and self.TYPE == 'imagewiz':
			self.specsub = SpecFigure(self,self.package.NAME[0] + ' IZ',spec_type='iz')
		elif not self.specsub and self.TYPE == 'imagewvz':
			self.specsub = SpecFigure(self,self.package.NAME[0] + ' VZ',spec_type='vz')
		else: pass



class Scanning2(object):
	'''
	This class coordinates the notebook panels for the image viewing and analysis. It starts by opening 2
	sample panels which show off to allow the user to mess around with the data analysis features of the
	program.
	'''
	cax = None
	imagespec = ['imagewiv','imagewzv','imagewiz']
	N_ALLOWED_TABS = ws.N_ALLOWED_TABS
	IM_ASPECT_W = ws.IM_ASPECT_W
	IM_ASPECT_H = ws.IM_ASPECT_H
	IM_ASPECT_SIZE = ws.IM_ASPECT_SIZE
	def __init__(self,nb,dataq=None,specq=None,homefrm=None):
		self.fig = Figure((7,6), 100)
		self.nb = nb
		if homefrm==None: editor=self.editor
		else: editor=homefrm.editor
		self.pages = {}
		self.x = None
		self.y = None
		self.ivsub = None
		self.coords = None
		self.package = None
		self.timelast = 0
		self.update = 0
		self.dataq = dataq
		self.specq = specq
		self.count = 0

		# Initialise the timer - wxPython requires this to be connected to
		# the receiving event handler
		self.t = wx.Timer(self, TIMER_ID)
		self.t.Start(100)

		# Open the sample panels
		number = 0
		fig = Figure((ws.IM_ASPECT_W,ws.IM_ASPECT_H), ws.IM_ASPECT_SIZE)
		asdf = FakePkg()
		self.pages['00000'] = NotebookPage(self,self.nb,number,editor=editor) # an image page
		self.pages['00000'].addToNotebook('00000') # append the page to the notebook
		self.pages['00000'].addPlot(fig,asdf,fake=True) # plot the data
		self.pages['00000'].lineN = 100
		
		fig = Figure((ws.IM_ASPECT_W,ws.IM_ASPECT_H), ws.IM_ASPECT_SIZE)
		asdf = FakePkg()
		self.pages['00001'] = NotebookSpec(self,self.nb,number) # a spectroscopy page
		self.pages['00001'].addToNotebook('00001') # append the page to the notebook
		self.pages['00001'].addPlot(fig,asdf,None) # plot the data
		
		sizer2 = wx.BoxSizer()
		sizer2.Add(self.nb, 1, wx.GROW, 0)
		self.SetSizer(sizer2)
		self.Bind(wx.EVT_TIMER, self.onTimer, id=TIMER_ID)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		
		# Note that event is a MplEvent
		self.statusBar = wx.StatusBar(self, -1)
		self.statusBar.SetFieldsCount(1)
		self.SetStatusBar(self.statusBar)
		#self.Show()

	
	def getData(self,editor=None,datapkg=None):
		'''
		Monitors the queue for any incoming data. If data is present,
		this function moves the data onto the notebook page. If the data comes
		from a new scan, a new page is added to the notebook.

		Keyword Arguments --
		editor - allows the editor object to be passed to the page if not
		already defined as an attribute of the class
		datapkg - used if data is already present, but other 
		'''
		if datapkg: pass
		else:
			try:
				datapkg = self.dataq.get(block=False)
				data = datapkg.data
				lineN = datapkg.LINE
				close = datapkg.close
				extent = datapkg.EXTENT
				datapkg.SCAN = str(datapkg.SCAN)
			except:
				datapkg = FakePkg()
				line = None
				close = False
		
		if datapkg.DATATYPE == 'line' or datapkg.DATATYPE == 'spec':
			if str(datapkg.SCANSTAMP) in self.pages.keys():
				self.pages[str(datapkg.SCANSTAMP)].Update(data,lineN)
			else:
				number = len(self.pages.keys())+2 #add 2 because of the stm and editor tabs
				fig = Figure((self.IM_ASPECT_W,self.IM_ASPECT_H), self.IM_ASPECT_SIZE)
				for key in self.pages.keys():
					if datapkg.SCAN in self.pages[key].SCAN:
						xs = 'XXXX'
						while xs in self.pages.keys():
							xs = xs+'X'
						self.nb.SetPageText(self.pages[key].pagenum,xs)
						self.pages[xs] = self.pages[key] # self.pages keeps track of the notebook tabs
						self.pages[xs].SCAN = xs
						self.pages.__delitem__(key)
				self.pages[str(datapkg.SCANSTAMP)] = NotebookPage(self,self.nb,number,editor=editor)
				self.pages[str(datapkg.SCANSTAMP)].addToNotebook(str(datapkg.SCAN))
				if datapkg.TYPE in self.imagespec:
					self.pages[str(datapkg.SCANSTAMP)].addPlot(fig,datapkg)
				else:
					self.pages[str(datapkg.SCANSTAMP)].addPlot(fig,datapkg)
				self.restrictNPages()
				if datapkg.DATATYPE == 'line': self.pages[str(datapkg.SCANSTAMP)].Update(data,lineN)
				elif datapkg.DATATYPE == 'spec': self.pages[str(datapkg.SCANSTAMP)].dispSpec(data)
		else: pass
	
	def SpecPage(self,datapkg):
		'''
		Adds a spectroscopy page to the notebook. Similar to getData().
		'''
		number = len(self.pages.keys())+2
		fig = Figure((self.IM_ASPECT_W,self.IM_ASPECT_H), self.IM_ASPECT_SIZE)
		for key in self.pages.keys():
			if datapkg.SCAN_NUMBER in self.pages[key].SCAN:
				xs = 'XXXX'
				while xs in self.pages.keys():
					xs = xs+'X'
				self.nb.SetPageText(self.pages[key].pagenum,xs)
				self.pages[xs] = self.pages[key]
				self.pages[xs].SCAN = xs
				self.pages.__delitem__(key)
		self.pages[str(datapkg.SCANSTAMP)] = NotebookSpec(self,self.nb,number)
		self.pages[str(datapkg.SCANSTAMP)].addToNotebook(str(datapkg.SCAN_NUMBER))
		self.pages[str(datapkg.SCANSTAMP)].addPlot(fig,datapkg,datapkg.TYPE[-2:])
		self.restrictNPages()
	
	def restrictNPages(self):
		'''
		Restricts the number of pages allowed in the notebook. First check if
		tabs have exceeded the allowed number and if it has, proceeds to delete the
		first available tab in the notebook.
		'''
		if len(self.pages.keys()) > self.N_ALLOWED_TABS:
			delpg = None
			for page in self.pages:
				if self.pages[page].pagenum == 2:
					delpg = page
				else: self.pages[page].pagenum -= 2
			if delpg:
				self.pages[delpg].delFromNotebook()
				self.pages.__delitem__(delpg)
		else: pass
	
	def _completed(self,fulldata):
		'''
		Once the full data package comes through the data collectors, all of
		the attributes of the scan are set.
		'''
		self.pages[str(fulldata.SCANSTAMP)]._set_complete(fulldata)

	def UpdateStatusBar(self, event):
		'''
		This function displays the xy coordinates in the statusbar. Needs to be outside the
		tab-level class because status bars are not unique to individual tabs.
		'''
		if event.inaxes:
			self.x, self.y = event.xdata, event.ydata
			self.x = int(round(self.x))
			self.y = int(round(self.y))
			try:
				if self.nb.GetCurrentPage().NB_TYPE == 'image':
					datapt = self.nb.GetCurrentPage().display[self.y][self.x]
				else: datapt = ''
			except: datapt = ''
			if datapt < 0: datapt = str(datapt)[0:6]
			else: datapt = str(datapt)[0:5]
			infostr = "x= "+str(self.x)[:5]+"  y="+str(self.y)[:5]+"  z="+datapt
			self.statusBar.SetStatusText((infostr),0)
	
	def finalData(self):
		'''
		Figures out what to do with the data received from
		the scan.
		
		'''
		data = self.panel.saveq.get()
		key = data.TYPE
		images = ['image','imagewiv','imagewiz','imagewzv','multibias','continuous']
		single_spec = ['singleiv','singleiz','singlezv']
		if key in images:
			self._completed(data)
		elif key in single_spec:
			self.SpecPage(data)
			self._completed(data)
			#iv_fig = SpecFigure(self,'IV Scan')
			#coords = str((0,0))
			#iv_fig._drawOnChange(coords,data.IV[coords])
		#elif key == 'singleiz':
			#iz_fig = SpecFigure(self,'IZ Scan',spec_type='iz')
			#coords = str((0,0))
			#iz_fig._drawOnChange(coords,data.IZ[coords])
		#elif key == 'singlezv':
			#zv_fig = SpecFigure(self,'ZV Scan',spec_type='zv')
			#coords = str((0,0))
			#zv_fig._drawOnChange(coords,data.ZV[coords])
		elif key == 'recovery':
			self.panel.newtree.treebytreename['image'].data['Offsets'][sv.XOFF[2]][0] = data.XOFF[0]
			self.panel.newtree.treebytreename['image'].data['Offsets'][sv.YOFF[2]][0] = data.YOFF[0]
			self.panel.newtree.treebytreename['image'].data['Image Parameters'][sv.SAMPLE_BIAS[2]][0] = data.SAMPLE_BIAS[0]
	
	def onTimer(self, evt):
		self.getData(editor=self.editor)
		if not self.panel.saveq.empty():
			self.finalData()

	def onClose(self, evt):
		self.t.Stop()
		evt.Skip()



class SpNavigationToolbar(NavigationToolbar2WxAgg):
	"""
	Extend the default wx toolbar with your own event handlers
	"""
	ON_UP = wx.NewId()
	ON_DOWN = wx.NewId()
	ON_ALL = wx.NewId()
	def __init__(self, parent, canvas, cankill):
		NavigationToolbar2WxAgg.__init__(self, canvas)
		self.parent = parent
		if self.parent.spec_type == 'iv':
			self.AddSimpleTool(self.ON_DOWN, _load_bitmap('stock_down.xpm'),
						'Move down a z-layer', 'Move down a z-layer')
			wx.EVT_TOOL(self, self.ON_DOWN, self._on_down)
			self.AddSimpleTool(self.ON_UP, _load_bitmap('stock_up.xpm'),
						'Move up a z-layer', 'Move up a z-layer')
			wx.EVT_TOOL(self, self.ON_UP, self._on_up)
			self.AddSimpleTool(self.ON_ALL, _load_bitmap('stock_refresh.xpm'),'Display All', 'Display All')
			wx.EVT_TOOL(self, self.ON_ALL, self._on_all)
		else: pass

	def _on_up(self, evt):
		self.parent.index += 1
		if self.parent.index > self.parent.max_index:
			self.parent.index = self.parent.max_index
		self.parent.plotSelection(self.parent.index,self.parent.display,self.parent.subplot2,labels=False)
		self.parent.plotSelection(self.parent.index,self.parent.data,self.parent.subplot,labels=False)
		self.parent.mode=0
		evt.Skip()
	
	def _on_down(self, evt):
		self.parent.index -= 1
		if self.parent.index < 0:
			self.parent.index = 0
		self.parent.plotSelection(self.parent.index,self.parent.display,self.parent.subplot2,labels=False)
		self.parent.plotSelection(self.parent.index,self.parent.data,self.parent.subplot,labels=False)
		self.parent.mode=1
		evt.Skip()
		
	def _on_all(self, evt):
		if self.parent.pdir == 0: self.parent.pdir = 1
		else: self.parent.pdir = 0
		self.parent.plotAll(self.parent.pdir,self.parent.display,self.parent.subplot2,labels=False)
		self.parent.plotAll(self.parent.pdir,self.parent.data,self.parent.subplot,labels=False)
		self.parent.mode=2
		evt.Skip()



class NotebookSpec(wx.Panel):
	'''
	A complementary class to NotebookPage. This handles the data/data analysis techniques for spectroscopy
	style data.
	'''
	NB_TYPE = 'spec'
	ASPECT_W = ws.ASPECT_W
	ASPECT_H = ws.ASPECT_H
	ASPECT_SIZE = ws.ASPECT_SIZE
	TITLE_SIZE = ws.TITLE_SIZE
	AXES_SIZE = ws.AXES_SIZE
	DEFAULT_COLOR = ws.DEFAULT_COLOR
	POINT_TYPE = ws.POINT_TYPE
	LINE_WEIGHT = ws.LINE_WEIGHT
	labels = {'i':ws.CURRENT_LABEL,'v':ws.BIAS_LABEL,'z':ws.HEIGHT_LABEL,\
	  'I':ws.CURRENT_LABEL,'V':ws.BIAS_LABEL,'Z':ws.HEIGHT_LABEL}
	unit_types = {}
	unit_types['I']=['Picoamps','Nanoamps','Microamps']
	unit_types['V']=['Millivolts','Volts']
	unit_types['Z']=['Volts','Angstroms','Nanometers','Microns']
	subplots = {'plot0':None,'plot1':None}
	pdir = 0
	max_index = 0
	gradpts = 3
	polyorder = 1
	sgderiv = 1
	def __init__(self,frame,parent,pagenum):
		wx.Panel.__init__(self,parent)
		self.parent = parent
		self.frame = frame
		self.pagenum = pagenum
	
	def addPlot(self,figure,datapkg,spec_type,addlabels=None):
		self.figure = figure
		self.spec_type = spec_type
		if hasattr(datapkg,'ZSCALE'): self.ZSCALE = datapkg.ZSCALE
		else: self.ZSCALE = 1
		if hasattr(datapkg, 'ZOUT'): self.ZOUT = datapkg.ZOUT
		else: self.ZOUT = 1.0
		if hasattr(datapkg, 'ZHV'): self.ZHV = datapkg.ZHV
		else: self.ZHV = 10.0
		self.UO = datapkg.UO
		self.canvas = FigureCanvasWxAgg(self, -1, figure)
		self.toolbar = SpNavigationToolbar(self,self.canvas, True)
		self.toolbar.Realize()
		self._set_layout(addlabels=addlabels)
		self.subplot = figure.add_subplot(211)
		self.subplot2 = figure.add_subplot(212)
		self.subplots = {'plot0':self.subplot,'plot1':self.subplot2}
		### Settings from old spec viewer ###
		self._resizeflag = True
		self.x = None
		self.y = None
		self.active = True
		self.index = 0
		self.max_index = 0
		#self.init_plot_data()
		xloc,yloc=0,0
		if spec_type != None:
			com='self.data=datapkg.'+string.upper(spec_type)+'[str((int(yloc),int(xloc)))]'
			exec com
			self.max_index = len(self.data)-1
		else:
			data = n.arange(1000)*0.01
			self.data = [[[data,(-n.sin(data*8.)-0.5*n.sin(data*2.)+n.random.random(1000))*15],[data,(n.sin(data*8.)+0.5*n.sin(data*2.)+n.random.random(1000))*15]]]
		self.display = deepcopy(self.data)
		self.plotSelection(0,self.data,self.subplot)
		####################################
		self.canvas.draw()
	
	def _set_layout(self,addlabels=None):
		panel_b = wx.Panel(self, -1)
		panel_c = wx.Panel(self, -1)
		panel_c.SetMinSize((127, 27))
		sizer = wx.FlexGridSizer(3, 1, 0, 0)
		sizer.AddGrowableRow(0,1)
		sizer.AddGrowableCol(0,1)
		sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW, 0)
		sizer.Add(self.toolbar, 1, wx.GROW, 0)
		sizer.Add(panel_c, 0, wx.GROW, 0)
		sizer2 = wx.BoxSizer(wx.VERTICAL)
		
		unitbox = wx.StaticBox(self, -1, 'Units')
		self.unit_type = wx.Choice(self, -1, choices=[])
		self.use_unit = wx.Choice(self, -1, choices=[])
		unitsizer1 = wx.BoxSizer(wx.HORIZONTAL)
		unitsizer2 = wx.BoxSizer(wx.HORIZONTAL)
		self.unit_type.SetMinSize((127,27))
		self.unit_type.Disable()
		self.use_unit.SetMinSize((127,27))
		self.use_unit.Disable()
		sizer2i = wx.StaticBoxSizer(unitbox,wx.VERTICAL)
		sizer2i.Add(self.unit_type, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2i.Add(self.use_unit, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2i.Add(unitsizer1, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2i.Add(unitsizer2, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		savgol = wx.StaticBox(self, -1, 'Savitzky-Golay')
		savsizer = wx.BoxSizer(wx.HORIZONTAL)
		sgptssizer = wx.BoxSizer(wx.HORIZONTAL)
		sgpts_label = wx.StaticText(self,-1,'# Points:')
		self.sgpts = wx.SpinCtrl(self, -1, str(5), min=1, max=30)
		sgpts_label.SetMinSize((63,27))
		self.sgpts.SetMinSize((63,27))
		sgptssizer.Add(sgpts_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		sgptssizer.Add(self.sgpts, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		pordersizer = wx.BoxSizer(wx.HORIZONTAL)
		porder_label = wx.StaticText(self,-1,'PolyOrder:')
		self.porder = wx.SpinCtrl(self, -1, str(1), min=1, max=5)
		porder_label.SetMinSize((63,27))
		self.porder.SetMinSize((63,27))
		pordersizer.Add(porder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		pordersizer.Add(self.porder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		dordersizer = wx.BoxSizer(wx.HORIZONTAL)
		dorder_label = wx.StaticText(self,-1,'DerivOrder:')
		self.dorder = wx.SpinCtrl(self, -1, str(1), min=0, max=5)
		dorder_label.SetMinSize((63,27))
		self.dorder.SetMinSize((63,27))
		dordersizer.Add(dorder_label, 0, wx.ADJUST_MINSIZE|wx.RIGHT|wx.TOP, 5)
		dordersizer.Add(self.dorder, 0, 0, wx.ADJUST_MINSIZE|wx.TOP, 5)
		self.sgupdate = wx.Button(self, -1, 'Apply')
		self.sgupdate.SetMinSize((127,27))
		sizer2f = wx.StaticBoxSizer(savgol,wx.VERTICAL)
		sizer2f.Add(sgptssizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(pordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(dordersizer, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2f.Add(self.sgupdate, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		
		fftbox = wx.StaticBox(self, -1, 'Fourier Transform')
		self.fftlog = wx.CheckBox(self, -1, label='Log Display')
		self.showfft = wx.Button(self, -1, 'Apply FFT')
		fftsizer = wx.BoxSizer(wx.HORIZONTAL)
		self.fftlog.SetMinSize((127,27))
		self.showfft.SetMinSize((127,27))
		sizer2g = wx.StaticBoxSizer(fftbox,wx.VERTICAL)
		sizer2g.Add(self.fftlog, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2g.Add(self.showfft, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		
		limbox = wx.StaticBox(self, -1, 'Limits')
		self.plotnumber = wx.Choice(self,-1,choices=self.subplots.keys())
		self.plotnumber.SetMinSize((127,27))
		lims0=wx.BoxSizer(wx.HORIZONTAL)
		lims1=wx.BoxSizer(wx.HORIZONTAL)
		lims2=wx.BoxSizer(wx.HORIZONTAL)
		lims3=wx.BoxSizer(wx.HORIZONTAL)
		lims4=wx.BoxSizer(wx.HORIZONTAL)
		xtxt = wx.StaticText(self,-1,'Xlims  ')
		xmi = wx.StaticText(self,-1,'min')
		xmi.SetMinSize((27,27))
		xma = wx.StaticText(self,-1,'max')
		xma.SetMinSize((28,27))
		ytxt = wx.StaticText(self,-1,'  Ylims')
		ymi = wx.StaticText(self,-1,'min')
		ymi.SetMinSize((27,27))
		yma = wx.StaticText(self,-1,'max')
		yma.SetMinSize((28,27))
		self.xminl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.xminl.SetMinSize((22,127))
		self.xmin = None
		self.xmaxl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.xmaxl.SetMinSize((22,127))
		self.xmax = None
		#ylims=wx.BoxSizer(wx.HORIZONTAL)
		self.yminl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.yminl.SetMinSize((22,127))
		self.ymin = None
		self.ymaxl = wx.Slider(self, -1, 0, -10, 10, (-1, -1), (250, -1), 
		wx.SL_AUTOTICKS | wx.SL_VERTICAL | wx.SL_LABELS)
		self.ymaxl.SetMinSize((22,127))
		self.ymax = None
		self.xmult_label = wx.StaticText(self,-1,'XMult/10')
		self.xmult_label.SetMinSize((62,27))
		self.xmult = wx.SpinCtrl(self,-1,'10',name='XMultiplier',min=1,max=99)
		self.xmult.SetMinSize((42,27))
		self.xmult_val = wx.StaticText(self,-1,'1.0')
		self.xmult_val.SetMinSize((22,27))
		self.ymult_label = wx.StaticText(self,-1,'YMult/10')
		self.ymult_label.SetMinSize((62,27))
		self.ymult = wx.SpinCtrl(self,-1,'10',name='YMultiplier',min=1,max=99)
		self.ymult.SetMinSize((42,27))
		self.ymult_val = wx.StaticText(self,-1,'1.0')
		self.ymult_val.SetMinSize((22,27))
		self.limapply = wx.Button(self, -1, 'Apply')
		self.limapply.SetMinSize((127,27))
		sizer2h = wx.StaticBoxSizer(limbox,wx.VERTICAL)
		lims0.Add(xtxt, 0, wx.ADJUST_MINSIZE|wx.RIGHT, 10)
		lims0.Add(ytxt, 0, wx.ADJUST_MINSIZE|wx.LEFT, 10)
		lims1.Add(xmi, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims1.Add(xma, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims1.Add(ymi, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims1.Add(yma, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 2)
		lims2.Add(self.xminl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims2.Add(self.xmaxl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims2.Add(self.yminl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims2.Add(self.ymaxl, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		lims3.Add(self.xmult_label, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		lims3.Add(self.xmult, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		lims3.Add(self.xmult_val, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		lims4.Add(self.ymult_label, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		lims4.Add(self.ymult, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		lims4.Add(self.ymult_val, 0, wx.ADJUST_MINSIZE|wx.TOP, 10)
		sizer2h.Add(self.plotnumber, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(lims0, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTRE|wx.ALL, 5)
		sizer2h.Add(lims1, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(lims2, 0, wx.ADJUST_MINSIZE|wx.LEFT|wx.RIGHT, 5)
		sizer2h.Add(lims3, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(lims4, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2h.Add(self.limapply, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)

		sizer2.Add(sizer2i, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2f, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2g, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(sizer2h, 0, wx.ADJUST_MINSIZE|wx.ALL, 5)
		sizer2.Add(panel_b, 1, wx.EXPAND, 0)
		if addlabels != None:
			grid_sizer_1 = wx.FlexGridSizer(1, 3, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer2, 1, wx.GROW, 0)
			grid_sizer_1.Add(addlabels, 1, wx.GROW, 0)
		else:
			grid_sizer_1 = wx.FlexGridSizer(1, 2, 0, 0)
			grid_sizer_1.AddGrowableRow(0,1)
			grid_sizer_1.AddGrowableCol(0,1)
			grid_sizer_1.Add(sizer, 1, wx.GROW, 0)
			grid_sizer_1.Add(sizer2, 1, wx.GROW, 0)
		self.SetSizer(grid_sizer_1)
		self.canvas.mpl_connect('motion_notify_event', self.frame.UpdateStatusBar)
		self.sgupdate.Bind(wx.EVT_BUTTON, self.OnSG)
		self.showfft.Bind(wx.EVT_BUTTON, self.OnFFT)
		self.limapply.Bind(wx.EVT_BUTTON, self.OnLimits)
		self.xmult.Bind(wx.EVT_SPINCTRL, self.OnXSpin)
		self.ymult.Bind(wx.EVT_SPINCTRL, self.OnYSpin)
		self.unit_type.Bind(wx.EVT_CHOICE, self.OnUnitSelect)
		self.use_unit.Bind(wx.EVT_CHOICE, self.OnUseUnit)

	def OnXSpin(self,event): self.xmult_val.SetLabel(str(int(self.xmult.GetValue())/10.))
	def OnYSpin(self,event): self.ymult_val.SetLabel(str(int(self.ymult.GetValue())/10.))

	def OnUnitSelect(self,event):
		unit=self.unit_type.GetStringSelection()
		if unit in self.unit_types.keys():
			self.use_unit.SetItems(self.unit_types[unit])
	
	def OnUseUnit(self,event):
		unit_type=self.use_unit.GetStringSelection()
		if hasattr(self,'package'):
			if unit_type == 'Z':
				self.display=self.UO._ConvertZScale(self.data,self.UO.ZVOLTS,self.UO.units[self.zunit][0],self.package.GAIN_ZHV[0],self.package.GAIN_ZOUT[0])
			elif unit_type == 'V':
				self.display=self.UO._Convert(self.data,self.UO.BIAS,self.UO.units[unit_type][0])
			elif unit_type == 'I':
				self.display=self.UO._Convert(self.data,self.UO.AMPS,self.UO.units[unit_type][0])

	def OnSG(self,event):
		gradpts = int(self.sgpts.GetValue())
		polyorder = int(self.porder.GetValue())
		sgderiv = int(self.dorder.GetValue())
		if sgderiv > polyorder:
			self.porder.SetValue(int(sgderiv))
			polyorder = sgderiv
		self.display = deepcopy(self.data)
		coeff = sg.calc_coeff(gradpts, polyorder, sgderiv)
		dx = float(self.display[0][0][0][-1:][0]-self.display[0][0][0][0])/len(self.display[0][0][0])
		corr = (1./dx)**sgderiv
		#if sgderiv != 0: corr *= -1
		#else: corr *= 1
		for i in range(len(self.display)):
			for j in range(2):
				#self.display[i][j][1] = self.display[i][j][1]-n.mean(self.display[i][j][1])
				self.display[i][j][1] = corr*sg.savitzky_golay(self.display[i][j][1],kernel=2*gradpts+1
				  ,order=polyorder,deriv=sgderiv)
				#self.display[i][j][1] = corr*sg.smooth(self.display[i][j][1],coeff)
		self.plotSelection(self.index,self.display,self.subplot2,labels=False)
	
	def OnFFT(self,event):
		for i in range(len(self.display)):
			for j in range(2):
				#self.display[i][j][1] = self.display[i][j][1]-n.mean(self.display[i][j][1])
				fft_data = n.fft.fft(self.display[i][j][1])
				self.display[i][j][1] = n.sqrt(n.real(fft_data)**2+n.imag(fft_data)**2)
		self.plotSelection(self.index,self.display,self.subplot2,labels=False)
	
	def plotSelection(self,index,data,subplot,labels=True):
		colors = ['g','r','b','c','y','m']
		xmax,xmin,ymax,ymin = (-10.1,10.1,-10.1,10.1)
		for j in range(2):
			if xmax < n.array(data[index][j][0]).max(): xmax = n.array(data[index][j][0]).max()
			if xmin > n.array(data[index][j][0]).min(): xmin = n.array(data[index][j][0]).min()
			if ymax < n.array(data[index][j][1]).max(): ymax = n.array(data[index][j][1]).max()
			if ymin > n.array(data[index][j][1]).min(): ymin = n.array(data[index][j][1]).min()
		if abs(ymax - ymin)<0.1:
			ymax += 0.01
			ymin -= 0.01
		subplot.clear()
		znf = subplot.plot(data[index][0][0],data[index][0][1],
		 self.POINT_TYPE,color=self.DEFAULT_COLOR[0],lw=self.LINE_WEIGHT)
		znr = subplot.plot(data[index][1][0],data[index][1][1],
		 self.POINT_TYPE,color=self.DEFAULT_COLOR[1],lw=self.LINE_WEIGHT)
		self.figure.subplots_adjust(left=0.15, bottom=0.05,top=0.9,right=0.85)
		axcolor = 'w'
		#Set some plot attributes
		if labels == True:
			subplot.set_title('Scan No. '+self.SCAN)
			subplot.set_ylabel("y Data (V)", fontsize = self.AXES_SIZE)
			subplot.set_xlabel("x Data (V)", fontsize = self.AXES_SIZE)
		#subplot.set_xlabel("Tip Bias (V)", fontsize = 16)
		#subplot.set_ylabel("Tunneling Current (mA)", fontsize = 16)
		subplot.set_xlim([xmin, xmax])
		subplot.set_ylim([ymin, ymax])
		subplot.legend([znf,znr],['z'+str(index)+'f', 'z'+str(index)+'r'], shadow=True)
		self.canvas.draw()
	
	def plotAll(self,direction,data,subplot,labels=True):
		layers = len(data)
		colors = ['g','r','b','c','y','m']
		xmax,xmin,ymax,ymin = (-10,10,-10,10)
		for i in range(layers):
			if xmax < n.array(data[i][direction][0]).max(): xmax = n.array(data[i][direction][0]).max()
			if xmin > n.array(data[i][direction][0]).min(): xmin = n.array(data[i][direction][0]).min()
			if ymax < n.array(data[i][direction][1]).max(): ymax = n.array(data[i][direction][1]).max()
			if ymin > n.array(data[i][direction][1]).min(): ymin = n.array(data[i][direction][1]).min()
		if abs(ymax - ymin)<0.1:
			ymax += 0.01
			ymin -= 0.01	
		subplot.clear()
		count = 0
		zn = []
		zind = []
		for i in range(layers):
			if direction == 0: direc = 'f'
			else: direc = 'r'
			zind.append('z'+str(i)+direc)
			zn.append(subplot.plot(data[i][direction][0],data[i][direction][1],\
			self.POINT_TYPE,color=self.DEFAULT_COLOR[count],lw=self.LINE_WEIGHT))
			count += 1
		self.figure.subplots_adjust(left=0.1, bottom=0.1,top=0.85,right=0.9)
		axcolor = 'w'
		#Set some plot attributes
		if labels==True and hasattr(self,package):
			subplot.set_title('Scan No. '+self.SCAN)
			subplot.set_xlabel(self.xlabel, fontsize = self.AXES_SIZE)
			subplot.set_ylabel(self.ylabel, fontsize = self.AXES_SIZE)
		subplot.set_xlim([xmin, xmax])
		subplot.set_ylim([ymin, ymax])
		subplot.legend(zn,zind, shadow=True)
		self.canvas.draw()
	
	def addToNotebook(self,title):
		self.parent.AddPage(self,title)
		self.SCAN = title
		self.parent.SetSelection(self.pagenum)
	
	def delFromNotebook(self):
		self.parent.RemovePage(self.pagenum)
	
	def OnLimits(self,event):
		plt=self.subplots[self.plotnumber.GetStringSelection()]
		try:
			self.xmin = float(self.xminl.GetValue())*float(self.xmult.GetValue())/10
			self.xmax = float(self.xmaxl.GetValue())*float(self.xmult.GetValue())/10
			if self.xmax < self.xmin: self.xmax = self.xmin+1
			xlims = (self.xmin,self.xmax)
		except: xlims = (-1,1)
		try:
			self.ymin = float(self.yminl.GetValue())*float(self.ymult.GetValue())/10
			self.ymax = float(self.ymaxl.GetValue())*float(self.ymult.GetValue())/10
			if self.ymax < self.ymin: self.ymax = self.ymin+1
			ylims = (self.ymin,self.ymax)
		except: ylims = (-1,1)
		self.setLim(plt,xlims,ylims)

	def setLim(self,subplot,xlims,ylims):
		subplot.set_xlim([xlims[0], xlims[1]])
		subplot.set_ylim([ylims[0], ylims[1]])
		self.canvas.draw()

	def _set_complete(self,fulldata):
		self.package = fulldata
		self.UO = fulldata.UO
		self.singletype = self.package.TYPE[-2:]
		typ0 = self.singletype[0]
		typ1 = self.singletype[1]
		self.ylabel = self.labels[typ0]
		self.xlabel = self.labels[typ1]
		self.unit_type.SetItems([string.upper(typ0),string.upper(typ1)])
		self.unit_type.Enable()
		self.use_unit.Enable()
